当前位置: 首页 > 工具软件 > Skeleton > 使用案例 >

stub/skeleton 极简理解

墨承泽
2023-12-01
  IPC, RPC, Stub与Skeleton相关  2012-09-06 15:30:52

分类: Java

理解跨进程通信,重点是理解stub与skeleton的关系 (一)Java api中有关RMI部分 见: http://download.oracle.com/javase/6/docs/api/index.html (二) java RMI规范部分 见:http://download.oracle.com/javase/6/docs/platform/rmi/spec/rmiTOC.html
这里有部分中文翻译: http://blog.chaoskey.com/2008/01/14/80 3.1 Stubs and Skeletons 5 Server Interfaces 8 Stub/Skeleton Interfaces  (三)实例(转): 见:http://ajava.org/course/java/16865.html

RMI工作原理 (自定义实现一个Stub 和 Skeleton)
     RMI的本质就是实现在不同JVM之间的调用,它的实现方法就是在两个JVM中各开一个Stub和Skeleton,二者通过socket通信来实现参数和返回值的传递。
     有关RMI的例子代码网上可以找到不少,但绝大部分都是通过extend the interface java.rmi.Remote实现,已经封装的很完善了,不免使人有雾里看花的感觉。下面的例子是我在《Enterprise JavaBeans》里看到的,虽然很粗糙,但很直观,利于很快了解它的工作原理。

1. 定义一个Person的接口,其中有两个business method, getAge() 和getName()
Person代码:

  1. public   interface  Person {      
  2.      public   int  getAge()  throws  Throwable;      
  3.      public  String getName()  throws  Throwable;        

2. Person的实现PersonServer类

PersonServer代码:

  1. public   class  PersonServer  implements  Person {      
  2.      private   int  age;      
  3.      private  String name;      
  4.      public  PersonServer(String name,  int  age) {      
  5.          this .age = age;      
  6.          this .name = name;      
  7.     }      
  8.      public   int  getAge() {      
  9.          return  age;      
  10.     }      
  11.      public  String getName() {      
  12.          return  name;      
  13.     }      
  14. }           

3. 好,我们现在要在Client机器上调用getAge()和getName()这两个business method,那么就得编写相应的Stub(Client端)和Skeleton(Server端)程序。这是Stub的实现:
Person_Stub代码:
//存根(stub)Person_Stub的实现:

  1. import  java.io.ObjectOutputStream;      
  2. import  java.io.ObjectInputStream;      
  3. import  java.net.Socket;      
  4. public   class  Person_Stub  implements  Person {      
  5.      private  Socket socket;      
  6.      public  Person_Stub()  throws  Throwable {      
  7.          // connect to skeleton      
  8.         socket =  new  Socket( "computer_name"  9000 );      
  9.     }      
  10.      public   int  getAge()  throws  Throwable {      
  11.          // pass method name to skeleton      
  12.         ObjectOutputStream outStream =      
  13.              new  ObjectOutputStream(socket.getOutputStream());      
  14.         outStream.writeObject( "age" );      
  15.         outStream.flush();      
  16.         ObjectInputStream inStream =      
  17.              new  ObjectInputStream(socket.getInputStream());      
  18.          return  inStream.readInt();      
  19.     }      
  20.      public  String getName()  throws  Throwable {      
  21.          // pass method name to skeleton      
  22.         ObjectOutputStream outStream =      
  23.              new  ObjectOutputStream(socket.getOutputStream());      
  24.         outStream.writeObject( "name" );      
  25.         outStream.flush();      
  26.         ObjectInputStream inStream =      
  27.              new  ObjectInputStream(socket.getInputStream());      
  28.          return  (String)inStream.readObject();      
  29.     }      
  30. }     

注意,Person_Stub和PersonServer一样,都implements Person。它们都实现了getAge()和getName()两个business method,不同的是PersonServer是真的实现,Person_Stub是建立socket连接,并向Skeleton发请求,然后通过 Skeleton调用PersonServer的方法,最后接收返回的结果。

4. 骨架(Skeleton)的实现
Person_Skeleton代码:

  1. import  java.io.ObjectOutputStream;      
  2. import  java.io.ObjectInputStream;      
  3. import  java.net.Socket;      
  4. import  java.net.ServerSocket;      
  5. public   class  Person_Skeleton  extends  Thread {      
  6.      private  PersonServer myServer;      
  7.      public  Person_Skeleton(PersonServer server) {      
  8.          // get reference of object server      
  9.          this .myServer = server;      
  10.     }      
  11.      public   void  run() {      
  12.          try  {      
  13.              // new socket at port 9000      
  14.             ServerSocket serverSocket =  new  ServerSocket( 9000 );      
  15.              // accept stub's request      
  16.             Socket socket = serverSocket.accept();      
  17.              while  (socket !=  null ) {      
  18.                  // get stub's request      
  19.                 ObjectInputStream inStream =      
  20.                      new  ObjectInputStream(socket.getInputStream());      
  21.                 String method = (String)inStream.readObject();      
  22.                  // check method name      
  23.                  if  (method.equals( "age" )) {      
  24.                      // execute object server's business method      
  25.                      int  age = myServer.getAge();      
  26.                     ObjectOutputStream outStream =      
  27.                          new  ObjectOutputStream(socket.getOutputStream());      
  28.                      // return result to stub      
  29.                     outStream.writeInt(age);      
  30.                     outStream.flush();      
  31.                 }      
  32.                  if (method.equals( "name" )) {      
  33.                      // execute object server's business method      
  34.                     String name = myServer.getName();      
  35.                     ObjectOutputStream outStream =      
  36.                          new  ObjectOutputStream(socket.getOutputStream());      
  37.                      // return result to stub      
  38.                     outStream.writeObject(name);      
  39.                     outStream.flush();      
  40.                 }      
  41.             }      
  42.         }  catch (Throwable t) {      
  43.             t.printStackTrace();      
  44.             System.exit( 0 );      
  45.         }      
  46.     }      
  47.      public   static   void  main(String args []) {      
  48.          // new object server      
  49.         PersonServer person =  new  PersonServer( "Richard"  34 );      
  50.         Person_Skeleton skel =  new  Person_Skeleton(person);      
  51.         skel.start();      
  52.     }      
  53. }     

Skeleton类 extends from Thread,它长驻在后台运行,随时接收client发过来的request。并根据发送过来的key去调用相应的business method。

5. 最后一个,Client的实现
PersonClient 代码:  

[java]  view plain copy
  1. public   class  PersonClient {        
  2.      public   static   void  main(String [] args) {        
  3.          try  {        
  4.             Person person =  new  Person_Stub();        
  5.              int  age = person.getAge();        
  6.             String name = person.getName();        
  7.             System.out.println(name +  " is "  + age +  " years old" );        
  8.         }  catch (Throwable t) {        
  9.             t.printStackTrace();        
  10.         }        
  11.     }        
  12. }   
  

Client(PersonClient)的本质是,它要知道Person接口的定义,并实例一个Person_Stub,通过Stub来调用business method,至于Stub怎么去和Server沟通,Client就不用管了。

注意它的写法:
Person person = new Person_Stub();而不是Person_Stub person = new Person_Stub();为什么?因为要面向接口编程嘛,呵呵。
//RMI实质上就是生成2个类stub,skeleton来进行参数和返回值的传递,采用值传递方式
//类似于以前写的聊天室程序,被传递的对象应实现java.io.Serializable接口


 类似资料: