【问题标题】:Debugging RMI connection调试 RMI 连接
【发布时间】:2014-08-30 05:42:38
【问题描述】:

我知道已经回答了稍微类似的问题,但我已经阅读了这些问题,但我仍然遇到问题。

我有一个服务器和一个客户端使用 RMI 相互连接。客户端在大学,服务器在家里。之所以这样做,是因为我可以完全控制家里的任何防火墙,但在大学里没有,我觉得这会给我最好的机会让它发挥作用。

我在同一台机器上使用“localhost”对它们进行了测试,这很好(家用和单机)。然后,我将服务器移动到运行 Windows Server 2012 的家用计算机上的虚拟机上。我可以远程桌面到该虚拟机,因为它设置为桥接连接并设置了端口转发。我还转发了 1099 端口。服务器在主服务器的顶部有这个:

System.setProperty("java.rmi.server.hostname", "localhost");
setRegistry(LocateRegistry.createRegistry(1099));
System.setSecurityManager(new RMISecurityManager());
Naming.rebind("rmi://localhost/" + AUTH_OBJECT_BINDING, server);

目前,安全管理器使用一个 security.policy 文件:

grant {
        permission java.security.AllPermission;
};

当我尝试将客户端连接到服务器时,将客户端命名查找中的“localhost”替换为我的家庭 IP,并允许 java 通过防火墙并设置端口转发,我得到以下信息:

java.rmi.ConnectException: Connection refused to host: xxx.xxx.xxx.xxx; nested exception is: 
    java.net.ConnectException: Connection timed out: connect

其中 xxx.xxx.xxx.xxx 是我正确的家庭 IP 地址。

所以,为了测试问题出在哪里,我在服务器 VM 上运行了客户端,但我没有使用 localhost,而是使用了我的外部 IP。这连接和工作。因此,由于我可以使用我的外部 IP 进行连接(从 217.137 开始...),我认为服务器可以正常接受连接。

我认为这意味着来自大学的出站连接存在问题。这可能是唯一的问题吗?我想排除一切。不幸的是,我无法访问不是家庭或 uni 的另一个网络,但使用我家的外部 IP 进行测试应该是相同的。

如果是这种情况,我可以在我的家用计算机上设置一个 SSH 服务器,我知道它可以在大学内部工作,并且可能使用 putty 和隧道,任何有关这方面的指导,或者如果它甚至可能真的会有所帮助。

为了清楚起见,我的问题分为两部分: 1)这可能是大学的出站规则阻止我连接到我的服务器。 2) 如果是,我该如何设置 Tunelling 以使用 RMI?

非常感谢任何帮助。

【问题讨论】:

    标签: java networking rmi


    【解决方案1】:
    System.setProperty("java.rmi.server.hostname", "localhost");
    

    这永远不会奏效。它需要设置为您的服务器的公共 IP 或主机名,您可以通过它通过 Internet 访问它。

    您在此处所做的是强制每个存根包含“localhost”作为其目标地址,如果客户端与服务器位于同一 localhost 中,这将起作用,但在其他情况下则不然。它必须是客户端可以用来连接到服务器的东西。

    通常情况下,您还需要通过 super(1099) 在端口 1099 上导出远程对象,这反过来意味着您必须通过 LocateRegistry.createRegistry() 运行注册表,确保将结果存储在一个静态变量,因此不会被垃圾回收。

    【讨论】:

    • 嗨,谢谢。所以我将其设置为 217.137.xxx.xxx(我的 IP)。 System.setProperty("java.rmi.server.hostname", "217.137.xxx.xxx");这是有道理的。在我的 Naming.rebind 上,我仍然使用它(因为它需要是 localhost): Naming.rebind("rmi://localhost/" + AUTH_OBJECT_BINDING, server);现在,当我尝试使用本地主机或外部 IP 从我的客户端(目前基于同一个虚拟机)连接时,我收到连接被拒绝异常。
    • 217.137.xxx.xxx 是你的公网 IP 地址吗?您是否在端口 1099 上导出远程对象?您是否在lookup() 上遇到异常?还是在执行远程方法时?
    • 217.137.xxx.xxx 是我的公共地址。我知道这是正确的,因为我目前正在将它用于远程桌面并且它工作正常(我现在在大学)。当我使用循环时我没有得到异常,但是当我调用返回的第一个方法时我得到了它。例如,我的客户有: authObject = (InterfaceAuth) Naming.lookup("rmi://217.137.xxx.xxx/" + AUTH_OBJECT_BINDING) 然后 session = authObject.Authenticate("user", "pass");然后我从这一行得到异常 java.rmi.ConnectException: Connection denied to host: 217.137.xxx.xxx;
    • 好。查找成功的事实表明网络基本上可以正常工作,并且顺便驳斥了@rthur 关于 RMI 和 NAT 的毫无根据的断言。现在你需要参加上面的出口备注。
    • 这意味着注册表已在端口 1099 上导出。对您的最后一个问题是。导出发生在构造时,而不是在绑定/重新绑定时。
    【解决方案2】:

    我手头没有任何具体的文档,但据我所知,RMI 不适用于 NAT。

    我假设您仍然能够从网络内部连接到服务器,因为您的路由器使用 nat loopback。

    【讨论】:

    • 感谢您的评论。我家用机器上的虚拟机使用直接(桥接)连接,所以我认为应该可以吗?或者我在这里遗漏了一些东西。
    • @EJP 据我所知,只有在java.rmi.server.hostname 属性设置为解析为私有内部的域名(而不是 IP)时,在 NAT 后面运行 RMI 服务器才有效NAT 网络内的 IP,以及网络外面向公众的 IP。
    • 你错了。如果它设置为公共主机名或 IP 地址并且映射了相应的端口,它将起作用。
    • 很公平 - 如果不使用正确的主机名,我从来没有设法让它在 NAT 后面成功工作。
    猜你喜欢
    • 2012-03-05
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    • 2013-11-05
    • 2017-12-05
    • 2021-07-30
    • 1970-01-01
    相关资源
    最近更新 更多