【问题标题】:RMI Chatprogram push configuration on external network not working外部网络上的 RMI Chatprogram 推送配置不起作用
【发布时间】:2016-11-08 11:47:11
【问题描述】:

我们正在尝试使用带有推送配置的 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;
            }

【问题讨论】:

  • 所以你有2路连接?客户端可以调用服务器上的方法,反之亦然?
  • @Antoniossss 是的,虽然可能不是制作聊天程序的最佳方式。我需要一些东西让客户端告诉服务器他发送了一条消息,并且需要一些东西让服务器将该消息广播给所有其他客户端。至少,我是这么理解的。
  • 一般来说你需要的是PUSH架构,而RMI是典型的PULL。 Insteed io 重新发明轮子,您为什么不使用已经存在且免费使用的技术进行类似聊天的通信(以及更多!),例如 XMPP?在过去,我已经成功地创建了基于 XMPP 并使用 OpenFire 服务器作为消息代理的聊天应用程序。您也可以使用消息队列来实现 PUSH 架构,以用于聊天应用程序。

标签: java chat push external rmi


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-20
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    相关资源
    最近更新 更多