有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

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