2016-03-07 231 views
1

我對Java RMI沒有太多經驗。我正在嘗試實施簡單的RMI通信,但遇到了問題。Java RMI客戶端和遠程服務器連接拒絕本地主機

這裏我RMI客戶

public class MainClientApplication { 

    public static final String FILE_NAME_RMI_POLICY = "rmi.policy"; 
    public static final String RMI_DOMAIN = "mydomain.net"; 
    public static final String RMI_ENDPOINT = "/MD5Decrypter"; 
    public static final String PROTOCOL = "rmi://"; 

    public static void main(String[] args) { 
     System.out.println(System.getProperty("user.dir") + File.separator + FILE_NAME_RMI_POLICY); 
     System.setProperty("java.security.policy", System.getProperty("user.dir") + File.separator + FILE_NAME_RMI_POLICY); 
     String remoteHost = String.format("%s%s%s", PROTOCOL, RMI_DOMAIN, RMI_ENDPOINT); 
     System.setSecurityManager(new SecurityManager()); 
     try { 
      ComputeEngine computeEngine = (ComputeEngine) Naming.lookup(remoteHost); 
      SwingUtilities.invokeLater(() -> new MainWindow("MD5 Decryption", computeEngine)); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

} 

通信inerface

public interface ComputeEngine extends Remote { 
    Object executeTask(Task t) throws RemoteException; 
} 

我的服務器

public class MainServer { 
    public static final int PORT = 1099; 
    public static final String RMI_ENDPOINT = "MD5Decrypter"; 
    public static final String FILE_NAME_RMI_POLICY = "rmi.policy"; 
    public static final String RMI_DOMAIN = "mydomain.net"; 
    public static final String PROTOCOL = "rmi://"; 

    public MainServer() { 
    try { 
     System.setProperty("java.security.policy", System.getProperty("user.dir") + File.separator + FILE_NAME_RMI_POLICY); 
     //System.setProperty("java.rmi.server.hostname", RMI_IP); 
     System.setProperty("java.rmi.server.hostname", RMI_DOMAIN); 
     System.setSecurityManager(new SecurityManager()); 
     ComputeEngine computeEngine = new ComputeEngineExecutor(); 
     // Naming.rebind(String.format("%s%s:%d/%s", PROTOCOL, RMI_DOMAIN, PORT, RMI_ENDPOINT), computeEngine); 
     Naming.rebind(RMI_ENDPOINT, computeEngine); 
     System.out.println("Successfully started RMI Server"); 
    } catch (RemoteException e) { 
     e.printStackTrace(); 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } 
} 

    public static void main(String[] args) { 
     MainServer mainServer = new MainServer(); 
    } 

} 

而且rmi.policy

grant { 
    permission java.net.SocketPermission "*:1024-65535", "connect, accept"; 
    permission java.io.FilePermission "-", "read"; 
    permission java.net.SocketPermission "*:80", "connect"; 
}; 

所以我在我的服務器rmiregistry 1099上啓動了rmiregistry。一切都很好,直到調用遠程對象方法。

這裏有

讓我們考慮,我的域名是mydomain.net,我使用靜態IP承載它在我的服務器在家裏我的腳步。在服務器上

  1. 運行rmiregistry
  2. 服務器上
  3. 運行服務器應用程序在任何PC上
  4. 運行客戶端應用程序
  5. 點擊按鈕來調用遠程方法

如此看來,一切所連接併成功綁定,因爲如果強制輸入無效域,端點或拒絕rmiregistry未啓動 - 引發java.rmi.ConnectException

但是,當我嘗試調用遠程對象上的任何方法,BTW這已被檢索到的成功,它拋出一個java.rmi.ConnectException

java.rmi.ConnectException: Connection refused to host: 127.0.1.1; nested exception is: 
    java.net.ConnectException: Connection refused 
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) 
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) 
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) 
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:130) 
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227) 
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179) 
    at com.sun.proxy.$Proxy0.executeTask(Unknown Source) 
    at ui.MainWindow.lambda$initGui$0(MainWindow.java:49) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) 
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 

,我可以理解,問題是它(服務器)迫使我連接到我的本地主機而不是遠程。

P.S localhost上一切完美(客戶端和服務器上的一臺PC上)

請幫助解決這個問題。

編輯

我忘了告訴大家,我試圖設置的java.rmi.server.hostname屬性,在這種情況下,它需要大量的時間來啓動服務器,並與異常結束。

+1

請參閱RMI FAQ項目A.1。 – EJP

+0

感謝您的回答,我已經嘗試設置'java.rmi.server.hostname',但它奇怪地工作,它需要大量的時間來啓動服務器和連接,但仍然無法工作 - 超時。 – CROSP

+1

你把它設置成什麼?你必須告訴我們你做了什麼。我們無法看到您的電腦。注意你必須在服務器JVM上設置* * – EJP

回答

1

拋開127.0.0.1的問題,java.rmi.server.hostname解決了,現在你的問題是連接超時。這將由您的防火牆引起。您需要將遠程對象導出到特定端口,並且需要在防火牆中打開該TCP端口。

+0

謝謝你的回答。 我從外部世界(路由器)轉發端口'1099'到我運行服務器的本地PC。 有趣的是,如果等待很長時間aprox。 5分鐘的服務器將啓動,並且客戶端可以連接到它(名稱查找),但是它又花費了很多時間,並且當我嘗試調用遠程方法時,它等待並超過5分鐘或更多時間後拋出超時異常 – CROSP

+1

端口1099註冊表端口。您需要另一個遠程對象。否則,在您的JVM中創建註冊表併爲兩者使用1099。超時是因爲所需端口未打開。您成功連接到註冊表,但不連接到遠程對象。聽起來像你也有一個巨大的DNS延遲。 – EJP

+0

非常感謝您的幫助,我也嘗試在代碼中以編程方式創建註冊表,但似乎是相同的情況。 據我所知,客戶端和服務器將使用隨機端口相互通信,我不想打開我的路由器中的所有端口。請你可以提供任何示例如何爲遠程對象指定通信端口。 – CROSP

相關問題