我对 Java 和 RMI 还很陌生,我决定尝试在我的家用计算机上为聊天客户端设置自己的服务器(仅用于学习目的,没有真正的用途)。总而言之,我使用套接字连接来发送消息,并使用 RMI 来进行服务器和客户端之间的通信。问题是我正在使用路由器,并且我希望客户端能够同时用于外部连接和内部连接(例如我的笔记本电脑 - 连接到与服务器相同的路由器)。
<小时/>我的公网IP是:109.99.33.251
我的本地IP地址是:196.168.1.9
问题是,如果我将 java.rmi.server.hostname 设置为
- 服务器本地IP:
- 一切都按预期运行,但仅限于从本地计算机访问服务器时。
- 当从外部机器访问时,只有套接字连接,rmi查找抛出连接拒绝:连接超时。 (我想提一下,我 99% 确定 RMI (1099) 和服务器 (5000) 的端口转发都已正确设置)
- 服务器公共(public)IP:一切正常,但仅适用于外部计算机。
- 当尝试从本地计算机与服务器的本地 IP 进行连接时,套接字连接正常,但 rmiregistry 查找方法失败。
- 当从本地计算机使用服务器的公共(public) IP 连接时,RMIregistry 和套接字都不会连接。
我的猜测是路由器有问题。我认为它不支持NAT loopback (使用它的公共(public)IP从LAN组件访问服务器)因为我从本地计算机连接到它的公共(public)IP的服务器永远不起作用,即使端口转发设置正确(它在外部连接两个服务器时都有效) RMI 和套接字连接)。
我能做些什么来完成这项工作吗?
编辑:
在服务器端,我在服务器启动后设置 System.setProperty("java.rmi.server.hostname","109.99.33.251");
,然后我:
LocateRegistry.createRegistry(1099);
然后我绑定(bind)对象:
MyRemote stub= new Communicator();
registry = LocateRegistry.getRegistry();
registry.bind("comm", stub);
其中 MyRemote 是扩展 Remote 接口(interface)的接口(interface),
通讯器是:
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
保存服务器的公共(public) IP 或本地 IP,具体取决于我之前介绍的情况。 serverPort
为 5000
为了让自己清楚,我希望客户端能够在本地和外部计算机上工作,因此我正在寻找一种方法来绑定(bind)远程对象并设置连接以使两者都工作(如果可能的话)。
注意:很抱歉,我对网络、java 和这个网站都很陌生,所以请不要介意我在提问时犯的错误。预先感谢您!
最终编辑:我已就此事联系了我的 ISP,他们说路由器具有最新的固件版本,而且它根本不支持 NAT 环回。
最佳答案
不幸的是,Oracle/Sun RMI 实现在这方面略有缺陷。有一个不必要的深层假设,即所有客户端都可见一个 IP 地址。您必须将 java.rmi.server.hostname 设置为 NAT 外部的公共(public) IP 地址,并且内部客户端必须能够使用该地址。
关于java - 如何使 RMI 服务器同时为本地客户端(同一网络内)和外部客户端工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31394031/