【问题标题】:How to make a RMI server work for both local clients (within the same network) and external clients如何使 RMI 服务器同时适用于本地客户端(在同一网络内)和外部客户端
【发布时间】:2015-10-02 08:19:26
【问题描述】:

我对 Java 和 RMI 还很陌生,因此我决定尝试在我的家用计算机上为聊天客户端设置自己的服务器(仅用于学习目的,没有实际用途)。总而言之,我使用套接字连接进行消息和 RMI 用于服务器和客户端之间的通信。问题是我正在使用路由器,并且我希望客户端能够同时用于外部连接和内部连接(例如,我的笔记本电脑 - 连接到与服务器相同的路由器)。


我的公网ip是:109.99.33.251
我的本地IP地址是:196.168.1.9
问题是,如果我将 java.rmi.server.hostname 设置为

  • 服务器本地 ip :
    • 一切都按预期工作,但仅在从本地计算机访问服务器时。
    • 当从外部机器访问时,只有套接字连接,rmi 查找抛出连接被拒绝:连接超时。 (我想提一下,我 99% 确定为 RMI (1099) 和服务器 (5000) 正确设置了端口转发)
  • 服务器公共 ip:一切正常,但仅适用于外部机器。
    • 当尝试从本地计算机与服务器的本地 ip 连接时,套接字连接正常,但 rmiregistry 查找方法失败。
    • 当从本地计算机使用服务器的公共 IP 连接时,RMIregistry 和套接字都不会连接。



我的猜测是路由器的问题。我认为它不支持NAT loopback(使用其公共 ip 从 LAN 组件访问服务器),因为即使端口转发设置正确(它在外部连接 RMI 和套接字连接时工作)。
我能做些什么来完成这项工作吗?

编辑: 在服务器端,我在服务器启动后设置System.setProperty("java.rmi.server.hostname","109.99.33.251");,然后我: LocateRegistry.createRegistry(1099);

然后我绑定对象:

MyRemote stub= new Communicator();
registry = LocateRegistry.getRegistry();
registry.bind("comm", stub);

其中 MyRemote 是扩展 Remote 接口的接口,并且 沟通者是:

public class Communicator extends UnicastRemoteObject implements MyRemote
{
    public Communicator() throws RemoteException
    {
        super(Registry.REGISTRY_PORT);
        System.out.println("I've created the host");
    }
    //the methods in the MyRemote
}`



对于我使用的套接字:

ServerSocket serverSock = new ServerSocket(5000);
while(true) 
{
    Socket clientSocket = serverSock.accept();
    ClientHandler handler =new ClientHandler(clientSocket);
    clients.add(handler);
    Thread t = new Thread(handler);
    t.start();
    System.out.println("got a connection");
}



对于客户端查找: service=(MyRemote) Naming.lookup("rmi://"+serverIp+"/comm");
对于套接字连接Socket socket=new Socket(serverIp,new Integer(serverPort));
serverIp 持有服务器的公共 IP 或本地 IP,这取决于我之前介绍的情况。 serverPort 是 5000


为了清楚起见,我希望客户端可以在本地和外部机器上工作,所以我正在寻找一种方法来绑定远程对象并设置连接以使两者都能工作,如果可能的话。

注意:对不起,我是networking,java和这个站点的新手,所以请不要介意我在提问时犯的错误。提前谢谢!

最终编辑:我已就此联系过我的 ISP,他们说路由器有最新的固件版本,它根本不支持 NAT 环回。

【问题讨论】:

  • 案例 2-(b):当使用服务器的公共 ip 从本地计算机连接时,RMIregistry 和套接字都没有连接...。为什么要呢?而且,关于其余的 - 没有代码就不能说太多了;如果出现连接超时错误,则会出现安全管理器/防火墙问题。
  • 感谢您的快速响应,我现在添加了代码。抱歉耽搁了,我不太习惯这个网站的格式要求。对于案例 2- (b) 我并不是说它应该有效,我只是在介绍我的案例。我完全不知道该怎么做才能让它发挥作用
  • 套接字连接是否与公共 IP 和端口 5000 转发一起工作?如果是这样,它似乎支持 NAT 环回。
  • 没有。如果 serverIp 的值为 109.99.33.251(公共 ip),则无论 java.rmi.server.hostname 值如何,套接字连接都不起作用
  • 在失败的情况下你会得到什么异常?连接超时?

标签: java sockets networking rmi nat


【解决方案1】:

不幸的是,Oracle/Sun RMI 的实现在这方面略有缺陷。有一个不必要的深层假设,即所有客户端都可以看到一个 IP 地址。您必须将java.rmi.server.hostname 设置为 NAT 外部的公共 IP 地址,并且内部客户端必须能够使用该地址。

【讨论】:

  • 感谢您的帮助。确实,正如我怀疑的那样,这可能是与路由器相关的问题。我将向我的 ISP 请求我的路由器的固件更新,因为我读到有时固件更新可能包括对 NAT 环回的支持。我会带着结果回来
猜你喜欢
  • 1970-01-01
  • 2021-05-02
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
相关资源
最近更新 更多