RMI Chatprogram外网推送配置不工作



我们正在尝试使用RMI和推送配置制作一个简单的聊天程序。该程序在内部网络上工作,但是当我们试图在外部网络上的服务器上运行该程序时,我们得到一个错误:

java.rmi.ConnectException: Connection refused to host: 192.168.2.24;
Caused by: java.net.ConnectException: Connection timed out: connect

当客户端在接口'IChatServer'上调用'Broadcast(String s)'方法时发生错误此方法位于服务器上,并调用服务器上订阅为侦听器的其他客户端。

我们的客户端可以连接到服务器。它可以从注册中心获取绑定,并从服务器调用方法。

但是当服务器试图从客户端调用一个方法时,我们得到这个错误。

服务器端转发1099端口,防火墙上允许1099端口。

是否有办法使这成为可能(使用RMI)?或者客户端的端口需要转发吗?

服务器:

  try {    
            String theIp = serverHostExternalIp;
            System.setProperty("java.rmi.server.hostname", theIp);
            //Implemented this so no random ports will be used
            RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
            registry = LocateRegistry.createRegistry(PORT_NUMBER);
            publisher = new RemotePublisher();
            publisher.registerProperty(BINDING_NAME);

            UnicastRemoteObject.unexportObject(server, true);
            UnicastRemoteObject.exportObject(server, PORT_NUMBER);
            UnicastRemoteObject.unexportObject(publisher, true);
            UnicastRemoteObject.exportObject(publisher, PORT_NUMBER);

            registry.rebind(BINDING_NAME, server);
            registry.rebind(PUBLISH_NAME, publisher);
        } catch (RemoteException ex) {
            System.err.println("[Server] Cannot bind student administration");
            System.err.println("[Server] RemoteException: " + ex.getMessage());
        }

IChatServer:

public synchronized void tryConnect(String s, IChatClient client) throws RemoteException {        
    System.out.println("[Server] User connected: " + s);
}
public synchronized void broadcast(String s) throws RemoteException {
    // When this line is called, no errors occur, and the string is printed correctly.
    System.out.println("[Message] " + s);
    //on this line, the server tries to reach to all the clients (all listeners)
    //This line of code will generate an error.
    publisher.inform(BINDING_NAME, null, s);
}
客户:

    try {
                registry = LocateRegistry.getRegistry(ipAddress, PORT_NUMBER);            
                mycs = (IChatServer) registry.lookup(BINDING_NAME);
                //This method is located on the server and is called without errors.
                mycs.tryConnect(userid, this);                    
                publisher = (IRemotePublisherForListener) registry.lookup(PUBLISH_NAME);                    
                publisher.subscribeRemoteListener(this, BINDING_NAME);
            } catch (RemoteException ex) {
                System.err.println("[Client] Cannot lookup or subscribe publisher");
                System.err.println("[Client] RemoteException: " + ex.getMessage());
                registry = null;
            } catch (NotBoundException e) {
                System.err.println("[Client] Cannot lookup or subscribe publisher");
                System.err.println("[Client] NotBoundException: " + e.getMessage());
                registry = null;
            }

对于RMI方式,不要将双方视为客户端-服务器,而是remote servicecaller

所以caller需要能够通过TCP连接到remote service,以便执行远程方法调用(RMI)。因此,在您的情况下,必须在两端正确设置端口转发。由于这可能会很麻烦(例如客户端可能位于未管理的NAT后面-就像您的情况一样),因此最好像REST服务一样威胁RMI -因此只有一方调用remote service

除了转发1099 (RMI注册端口),您还必须转发导出对象使用的端口。RMI注册表只保存有关如何连接到实际导出的对象处理程序的信息。

最新更新