在RMI中有四个地方出现了端口的概念1  static Remote
exportObject(Remote obj, int port) 
          使用提供的特定端口导出远程对象,以便能够接收传入的调用。
2 LocateRegistry.createRegistry( PORT );3   String urlString = "//" + HOST_NAME + ":" + Integer.toString( PORT ) + "/" + "HelloService";
 Naming.rebind( urlString, h );4 h = (Hello)Naming.lookup( "rmi://" + HOST_NAME + ":" + Integer.toString( PORT ) + "/HelloService" );
但据我的实验,2 与 3中的port可以不一样,不影响正常使用。
port之间的关系如何?这些地方的port一定要一样么?

解决方案 »

  1.   

    Remote调用
    1 你必须知道注册服务在哪里?
    2 你必须知道服务所在的端口所以至少应该有2个端口,一个负责注册服务,另一个提供服务。
      

  2.   

    1L说的对你可以看看这个http://blog.163.com/xiao_maomao_chong/blog/static/31686239200861744356634/
      

  3.   

    如果是2个端口,那么应该是启动了2个RMI服务
    你的服务是注册到哪个端口,就必须到哪个端口调用
      

  4.   

            //启动RMI注册服务,指定端口为1099 (1099为默认端口)             //也可以通过命令 $java_home/bin/rmiregistry 1099启动             //这里用这种方式避免了再打开一个DOS窗口             //而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用             LocateRegistry.createRegistry(1099);  
      

  5.   

    http://blog.163.com/xiao_maomao_chong/blog/static/31686239200861744356634/
    这个帖子说得很好
    但是关于他对于rmic 和 stub的说法 不敢苟同。
    我知道在5.0后JDK版本支持不使用rmic的一种用法
    服务器端:
     try {
            PaymentImpl robj = new PaymentImpl();
            Payment stub = (Payment) UnicastRemoteObject.exportObject(robj, 0);        Registry registry = LocateRegistry.getRegistry();
            registry.bind("Mortgage", stub);
            System.out.println("Mortgage Server is ready to listen");    } catch (Exception e) {
              }
        }
    客户端:
    try {
            Registry reg = LocateRegistry.getRegistry("localhost");
            stub = (Payment) reg.lookup("Mortgage");
            
        } catch (Exception e)但是,在http://blog.163.com/xiao_maomao_chong/blog/static/31686239200861744356634/
    例子中,仍然是使用的Naming.rebindLocateRegistry.createRegistry(1099);               HelloInterface hello = new Hello("Hello, world!");          //把hello注册到RMI注册服务器上,命名为Hello             Naming.rebind("Hello", hello);   
    这种方式启动,虽然不需要再于命令行启动rmiregistry,但还是要用rmic 生成stub否则
    java.rmi.StubNotFoundException: Stub class not found: RMIServer_Stub; nested exc
    eption is:
            java.lang.ClassNotFoundException: RMIServer_Stub
      

  6.   

    我上面的帖子错了,因为http://blog.163.com/xiao_maomao_chong/blog/static/31686239200861744356634/中
    远程对象扩展了UnicastRemoteObject,所以不需要stub    第3种方式 需要 rmic  出 一个 stub ,而第1种方式不需要。
                     
                 1 RMI  : difference between the  "extends UnicastRemoteObject" and  Payment stub = (Payment) UnicastRemoteObject.exportObject(robj, 0); and the 
    2new edition 5.0后 :
    Payment stub = (Payment) UnicastRemoteObject.exportObject(robj, 0); 这种方式如果把0 去掉,采用匿名,就找不到stub
            Registry registry = LocateRegistry.getRegistry(); 
            registry.bind("Mortgage", stub);
    3older edition,5.0前 : need the stub by rmic 
          UnicastRemoteObject.exportObject( bm );   这种方式 需要 rmic stub ,而第一中方式不需要
    如果使用 UnicastRemoteObject.exportObject(Remote) 方法导出该远程对象,则加载 stub 类(通常使用 rmic 工具从远程对象的类预生成)并按以下方式构造 stub 类的实例。 
    “根类”按以下情形确定:如果远程对象的类直接实现扩展 Remote 的接口,则远程对象的类为根类;否则,根类为直接实现扩展 Remote 接口的远程对象类的最具派生能力的超类。 
    要加载的 stub 类的名称通过连接带有后缀 "_Stub" 的根类的二进制名称确定。 
    按使用根类的类加载器的名称加载 stub 类。该 stub 类必须扩展 RemoteStub 并且必须有公共构造方法,该构造方法有一个属于类型 RemoteRef 的参数。 
    最后,用 RemoteRef 构造 stub 类的实例。 
    如果无法找到适当的 stub 类,或无法加载 stub 类,或创建 stub 实例时出现问题,则抛出 StubNotFoundException。 
             Naming.rebind("//localhost/BankSystem", bm)
      

  7.   

    答:完全正确!rmiregistry 在自己的端口号上完成注册与查询服务,而UnicastRemoteObject在自己的端口号上完成远程服务.而这两个端口号是不相同的.若UnicastRemoteObject没有选择自己的PORT,是系统自动帮它选择一个.
      

  8.   

    但是,客户端只需要知道rmiregistry 的端口号就行了,对吧
      

  9.   

    答:"但是,客户端只需要知道rmiregistry 的端口号就行了,对吧"  
     是的.