【问题标题】:RMI starts two servers in localhost but different port at the same timeRMI 在 localhost 中同时启动两台服务器,但端口不同
【发布时间】:2018-02-27 08:36:37
【问题描述】:

我正在学习RMI,想知道是否可以用不同的端口启动两台服务器,以及如何实现?

该程序有一个客户端和两个服务器。 Server1 使用 RMI 默认端口 1099。Server2 使用端口 1098(我已检查端口 1098 未使用)。

服务器1:

public static void main(String[] args) {
    try {
        Server obj = new Server();
        Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);

        Registry registry = LocateRegistry.getRegistry();
        registry.bind("Hello", stub);

        System.out.println("Server 1 ready");
    } catch (Exception e){
        System.err.println("Server exception: " + e.toString());
        e.printStackTrace();
    }
}

服务器2

public static void main(String[] args) {
    try {
        ServerTwo obj = new ServerTwo();
        HelloTwo stub = (HelloTwo) UnicastRemoteObject.exportObject(obj, 0);

        Registry registry = LocateRegistry.createRegistry(1098);
        registry = LocateRegistry.getRegistry(1098); 
        registry.bind("HelloTwo", stub);

        System.out.println("Server 2 ready");
    } catch (Exception e){
        System.err.println("Server exception: " + e.toString());
        e.printStackTrace();
    }
}

编译运行服务器:

javac *java
rmic Server
rmiregistry 1099 &
rmic ServerTwo
rmiregistry 1098 &

顺便说一下,1099端口和1098端口的进程名是不同的。 我通过lsof -i tcp:portnumber检查了端口,发现端口1099和1098分别有两个进程。但是端口 1099 显示名称是 *:rmiregistry (LISTEN)。端口 1098 显示名称为 *:rmiactivation (LISTEN)。为什么它们不同?这是什么意思?这是否与以下错误有关?

启动Server2时出现如下错误:

Server exception: java.rmi.server.ExportException: Port already in use: 1098; nested exception is: 
java.net.BindException: Address already in use 
java.rmi.server.ExportException: Port already in use: 1098; nested exception is: 
java.net.BindException: Address already in use
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:341)
at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:249)
at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:411)
at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:147)
at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:208)
at sun.rmi.registry.RegistryImpl.setup(RegistryImpl.java:152)
at sun.rmi.registry.RegistryImpl.<init>(RegistryImpl.java:137)
at java.rmi.registry.LocateRegistry.createRegistry(LocateRegistry.java:203)
at ServerTwo.main(ServerTwo.java:20)
Caused by: java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createServerSocket(RMIDirectSocketFactory.java:45)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createServerSocket(RMIMasterSocketFactory.java:345)
at sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:666)
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:330)
... 8 more

显示1098端口正在使用中...是的,Server2使用该端口...如何解决?我对 RMI 和端口连接感到困惑。

=============

编辑:

添加客户端代码:

public static void main(String[] args) {
    String host = (args.length < 1) ? null : args[0];

    try {
             Registry registry = LocateRegistry.getRegistry(host);
             Hello stub = (Hello) registry.lookup("Hello");
             String response = stub.sayHello();
             System.out.println("response 1: " + response);

             HelloTwo stub2 = (HelloTwo) registry.lookup("HelloTwo");
             String response2 = stub2.sayHello();
             System.out.println("response 2: " + response2);

    } catch (Exception e) {
        System.err.println("Client exception: " + e.toString());
        e.printStackTrace();
    }
}

【问题讨论】:

    标签: java rmi


    【解决方案1】:

    您不需要两个注册表。如果注册表和远程对象都是由同一个 JVM 创建的,您甚至不需要两个端口。你只需要:

    • 将两个远程对象放到同一个 JVM 中
    • 致电LocateRegistry.createRegistry(Registry.REGISTRY_PORT)
    • 然后创建并导出两个远程对象。

    这样,所有东西都将监听 1099 端口。

    1098端口显示名字是*:rmiactivation (LISTEN).为什么不一样?

    因为端口 1098 是为 RMI 激活守护进程保留的,这就是 lsof 知道的全部内容。

    【讨论】:

    • hew 想要两个使用两个 rmiRegistry 而不是一个
    • 这是他的问题,(同时不同的端口)
    • @AzzabiHaythem 如果他想浪费宝贵的资源,他可以使用任意数量的ports,但他仍然不需要两个Registries,而他没有说过他想这样做。
    • 是的,你是对的。我更改了Client 代码以在一个注册表上查找具有不同注册表名称的 Server1 和 Server2。但是你的第二点是如何工作的?是服务器端还是客户端?
    • @Helen 在导出两个远程对象的同一个 JVM 中。我已经说过了。
    猜你喜欢
    • 2017-11-18
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    相关资源
    最近更新 更多