2010-06-15 116 views
3

我一直在此项目中使用RMI。Java RMI无法从外部客户端连接到主机

java.rmi.ConnectException: Connection refused to host: (private IP of host machine); nested exception is: 
java.net.ConnectException: Connection timed out: connect 
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source) 
at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source) 
at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source) 
at sun.rmi.server.UnicastRef.invoke(Unknown Source) 
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source) 
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) 
at $Proxy1.ping(Unknown Source) 
at client.Launcher$PingLabel.runPing(Launcher.java:366) 
at client.Launcher$PingLabel.<init>(Launcher.java:353) 
at client.Launcher.setupContentPane(Launcher.java:112) 
at client.Launcher.<init>(Launcher.java:99) 
at client.Launcher.main(Launcher.java:59) 

Caused by: java.net.ConnectException: Connection timed out: connect 
at java.net.PlainSocketImpl.socketConnect(Native Method) 
at java.net.PlainSocketImpl.doConnect(Unknown Source) 
at java.net.PlainSocketImpl.connectToAddress(Unknown Source) 
at java.net.PlainSocketImpl.connect(Unknown Source) 
at java.net.SocksSocketImpl.connect(Unknown Source) 
at java.net.Socket.connect(Unknown Source) 
at java.net.Socket.connect(Unknown Source) 
at java.net.Socket.<init>(Unknown Source) 
at java.net.Socket.<init>(Unknown Source) 
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source) 
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source) 
... 12 more 

此错误是:我已经在我运行到以下异常互联网上运行时,它在我的局域网上运行它的时候,但得到的客户端程序连接(除其他事项外)服务器如果我在没有运行服务器程序的情况下在本地运行客户端,则可以再现我早期实现的RMI并获得错误verbatum。对我来说,连接超时意味着服务器的响应出现问题。

这里的客户开始:

public static void main(String[] args) 
{ 
    try 
    { 
     String host = "<WAN IP>"; 
     Registry registry = LocateRegistry.getRegistry(host, 1099); 
     Login lstub = (Login) registry.lookup("Login Server"); 
     Information istub = (Information) registry.lookup("Game Server"); 
     new Launcher(istub, lstub); 

    } 
    catch (RemoteException e) 
    { 
     System.err.println("Client exception: " + e.toString()); 
     e.printStackTrace(); 
    } 
    catch (NotBoundException e) 
    { 
     System.err.println("Client exception: " + e.toString()); 
     e.printStackTrace(); 
    } 
} 

有趣的是没有远程异常这里抛出。 这里的服务器启动:

public static void main(String args[]) 
{ 
    try 
    { 
     GameServer gobj = new GameServer(); 
     Information gstub = (Information) UnicastRemoteObject.exportObject(
       gobj, 1099); 
     Registry registry = LocateRegistry.createRegistry(1099); 
     registry.bind("Game Server", gstub); 

     LoginServer lobj = new LoginServer(gobj); 
     Login lstub = (Login) UnicastRemoteObject.exportObject(lobj, 7099); 

     // Bind the remote object's stub in the registry 
     registry.bind("Login Server", lstub); 

     System.out.println("Server ready"); 
    } 
    catch (Exception e) 
    { 
     System.err.println("Server exception: " + e.toString()); 
     e.printStackTrace(); 
    } 
} 

与赶上(例外五)坏的做法,但我知道多多包涵。

直到这个阶段,我知道它在局域网很好,这里的地方例外发生在广域网和是首位在服务器中调用一个方法:

private class PingLabel extends JLabel 
{ 
    private static final long serialVersionUID = 1L; 

    public PingLabel() 
    { 
     super(""); 
     runPing(); 
    } 

    public void setText(String text) 
    { 
     super.setText("Ping: " + text + "ms"); 
    } 

    public void runPing() 
    { 
     try 
     { 
      PingThread pt = new PingThread(); 
      gameServer.ping(); 
      pt.setRecieved(true); 
      setText("" + pt.getTime()); 
     } 
     catch (RemoteException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

这是放置在一个标签发射器作为一个ping测试。 ping()方法在gameserver中不起作用,因为in是一个null方法。

值得注意的是端口1099和7099被转发到服务器机器(这应该从堆栈跟踪中显而易见)。

任何人都可以看到我失踪/做错了吗?如果您需要更多信息,请询问。

编辑:我几乎肯定这个问题与我的路由器设置无关。当禁用我的端口转发设置我得到一个稍微不同的错误:

Client exception: java.rmi.ConnectException: Connection refused to host: (-WAN IP NOT LOCAL IP-); 

,但似乎都在本地机器上连接到服务器,并在远程机器上。当我连接服务器时直接连接到调制解调器(切断路由器,我只能得出结论,问题出在我的路由器的设置中,但无法看到在哪里(我检查过了,双重检查端口转发页)这是我能想出的唯一答案

+0

您是否100%确定您可以通过网络连接到目标机器上的端口1099和7099?你是否尝试telnet到源机器的端口来测试连接?例如,尝试'telnet 1099'。如果它连接,那么连接就很好 - 否则你需要查看阻塞连接的东西。 – 2010-06-15 11:48:32

+0

我现在无法测试,但是我的本地IP被列在堆栈跟踪中,我以为连接正在工作(某种程度上)。 – Herrad 2010-06-15 12:45:15

回答

2

您是否使用NAT(网络地址转换)?这是典型的情况,如果您的LAN使用路由器后面的不可路由地址(如10.x或192.169.x等)

如果是这种情况,您需要使用以下选项指定服务器的公共IP:

-Djava.rmi.server.hostname=host_name_or_public_ip 
+0

我还没有访问我的远程机器atm,所以我现在不能测试它,但肯定这是'String host =“”; Registry registry = LocateRegistry.getRegistry(host,1099);' 代码是不是? – Herrad 2010-06-15 12:43:27

+0

如果您的机器是多宿主机,则可以侦听WAN IP。否则,您需要监听本地IP,因为机器甚至不拥有WAN IP(它属于路由器)。 – 2010-06-15 15:01:02

+0

'String host =“”;注册表注册表= LocateRegistry.getRegistry(主机,1099);'位于客户端,它告诉客户端从服务器正在监听的端口上的服务器的WAN IP获取注册表(或者这是我的理解)。 所以我会认为-Djava.rmi选项是多余的。 – Herrad 2010-06-16 02:29:54