java如何使RMI服务器同时适用于本地客户端(在同一网络中)和外部客户端
我对Java和RMI非常陌生,我决定尝试在家用电脑上为聊天客户端设置自己的服务器(只是为了学习,没有真正的用途)。总之,我使用socket连接进行消息传输,使用RMI进行服务器和客户机之间的通信。问题是,我使用的是路由器,我希望客户端能够同时进行外部连接和内部连接(例如,我的笔记本电脑——与服务器连接到同一路由器)
我的公共ip是:109.99.33.251
我的本地ip地址是:196.168.1.9
问题是如果我设置java。rmi。服务器主机名到
- 服务器本地ip:
- 一切正常,但只有在从本地机器访问服务器时才能正常工作李>
- 当从外部机器访问时,只有socket连接,rmi查找抛出连接拒绝:连接超时。(我想提到的是,我99%确定RMI(1099)和服务器(5000)的端口转发都已正确设置。)
- 服务器公共ip:一切正常,但只适用于外部机器。
- 当尝试使用服务器的本地ip从本地计算机连接时,socket连接良好,但RMI注册表查找方法失败李>
- 当使用服务器的公共ip从本地计算机连接时,注册中心和socket都不会连接
我猜这是路由器的问题。我认为它不支持NAT loopback(使用公共ip从LAN组件访问服务器),因为从本地机器连接到服务器(公共ip)对我来说从来都不起作用,即使端口转发设置正确(在外部连接RMI和socket连接时,它也起作用)
我能做些什么来实现这一点吗?
编辑:
在服务器端,我在服务器启动后设置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是扩展远程接口和
沟通者是:
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 socket=new Socket(serverIp,new Integer(serverPort));
serverIp
持有服务器的公共ip或本地ip,具体取决于我前面介绍的情况。而且serverPort
是5000
为了明确起见,我希望客户机在本地和外部机器上都能工作,所以我正在寻找一种方法来绑定远程对象,并设置连接以使两者都能工作,如果可能的话
注:很抱歉,我对网络、java和本网站不熟悉,所以请不要介意我在提问时犯的错误。提前谢谢
最后编辑:我已经联系了我的ISP,他们说路由器有最新的固件版本,不支持NAT环回
# 1 楼答案
不幸的是,Oracle/Sun RMI的实现在这方面略有缺陷。有一个不必要的深层次假设,即所有客户端都可以看到一个IP地址。您必须将
java.rmi.server.hostname
设置为NAT外部的公共IP地址,内部客户端必须能够使用该地址