2010-06-15 119 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