1

这是我在 stackoverflow 中的第一篇文章,我正在尝试使用 RMI 实现聊天,但我被卡住了,我正在避免使用 rmiregistry,一切都在 localhost 上很好地绑定,但我需要它可以从互联网上访问,端口被转发,防火墙关闭,实际上我可以通过互联网检索一个对象,我已经使用

System.setProperty("java.rmi.server.hostname","ruso.89.x.ignorelist.com");

那么我的 NameServer.java 绑定到该 IP,但我失去了通过 localhost 的所有访问权限,现在让我解释一下。这是 NameServer.java 的代码

public class NameServer
{
   public static void main (String args [] )
   {
    String direscucha = "ruso.89.x.ignorelist.com";
    int puertonombres = 5000;
    try{

        System.setProperty("java.rmi.server.hostname", direscucha);          
        System.setProperty("java.security.policy", "C:\\Users\\Antonio\\Desktop\\DistributedChat\\myServer.policy");
        System.setSecurityManager(new RMISecurityManager());
        NameService ns = new NameService();
        Registry reg=LocateRegistry.createRegistry(puertonombres);
        reg.rebind("ns",ns);
        while(true){}
    }catch(Exception e){
        System.out.println(e);
    }
  }
}

这是我的政策文件:

grant {
permission java.security.AllPermission;
permission java.net.SocketPermission "ruso.89.x.ignorelist.com:*", "connect,resolve,accept";
permission java.net.SocketPermission "localhost:*", "connect,resolve,accept";
permission java.net.SocketPermission "127.0.0.1:*", "connect,resolve,accept";
};

然后我需要运行 ChatServer.java,这需要 ns 并将自己绑定到它,所以可以找到 ChatServer,问题是当我从 LAN 外部使用它时,我可以让服务器运行!但是当我使用 localhost 时出现异常

ChatServer.java (片段)

public void work ()
{
    String direscucha = "ruso.89.x.ignorelist.com";        
    int puertonombres = 5000;
    System.setProperty("java.rmi.server.hostname", direscucha); //Binds to the Public IP
    System.setProperty("java.security.policy", "C:\\Users\\Antonio\\Desktop\\DistributedChat\\myClient.policy"); //marca la politica
    System.setSecurityManager(new RMISecurityManager()); //Ejecuta el RMISecurityManager
    try
    {                                    
        String[] list = Naming.list("//localhost:5000/"); //Debugging
        System.out.println("Tamanyo: "+list.length);      
        for(int i=0; i<list.length; i++)                  
            System.out.println(list[i]);
        NameService_Stub ns =  (NameService_Stub) Naming.lookup("rmi://localhost:5000/ns");

        ns.rebind (conf.getServerName(), this);
        System.out.println("Servidor registrado::");
    }
    catch (java.rmi.ConnectException e)
    {
        System.out.println (e);
        System.exit(-1);            
    }
    catch (Exception e)
    {
        System.out.println(e);
        System.exit(-1);
    }

因此,当现在注册 ServerChat 时,任何用户都可以执行 ChatClient.java 以从 NameService 中检索 ChatServer 的名称,然后进行连接,但由于我无法管理 ChatServer 工作,所以还没有到达那里。我的第一个想法是,在设置主机名属性时,localhost 获取被阻止但没有提及,之后我认为这可能是路由器 NAT 的问题,可能是这样吗?

例外:

java.rmi.ConnectException: Connection refused to host: ruso.89.x.ignorelist.com; nested exception is:
java.net.ConnectException: Connection refused: connect

客户端和服务器策略文件是相同的。使用 WireShark 查看发生了什么,发送 SYN 并收到 ACK,RST。我已经把我所有的想法都烧掉了,有什么建议吗?

4

1 回答 1

0

我已经使用

System.setProperty("java.rmi.server.hostname","ruso.89.x.ignorelist.com");

那么我的 NameServer.java 绑定到该 IP

不,它没有。这是一个常见的误解,但不正确。RMI 始终将其绑定ServerSockets到 0.0.0.0,除非您提供RMIServerSocketFactory其他方式。的效果java.rmi.server.hostname是将其值嵌入到存根中(本质上而不是返回的值InetAddress.getLocalHost())。

   while(true){}

您不需要通过这样做来吸烟您的 CPU,但您确实需要使Registry引用成为静态变量。当您导出远程对象时,RMI 会启动一个线程,这将阻止 JVM 退出,直到您取消导出它为止。当远程对象被垃圾收集时,取消导出会自动发生,静态引用会阻止这种情况。

连接拒绝托管:ruso.89.x.ignorelist.com

这可能意味着您的内部防火墙不允许您向外连接到该主机,即使它是您自己的。或者ruso.89.x.ignorelist.com在您的网络中有不同的、不正确的 DNS 映射。

于 2013-05-24T00:45:56.360 回答