簡體   English   中英

互聯網上的Java RMI

[英]Java rmi over the internet

我正在使用RMI開發一個Java游戲,用於所有網絡通信。 RMI允許我在服務器上調用方法,但這對我來說還不夠。 我還希望服務器能夠在連接的客戶端之間傳播消息。

我的客戶查找服務器(它的接口擴展為Remote)並在其上注冊。 它允許服務器知道誰連接了。 我的客戶端還實現了擴展Remote的接口。 這是我的代碼的一部分:

接口聲明:

public interface IServer extends Remote {
    void connect(IClient Client) throws RemoteException, ExistingItemException;
    //...
}

public interface IClient extends Remote {
    public void notify(Notification Notification) throws RemoteException;
    //...
}

服務器端:

//int RMIPort = 1099, ServerPort = 1100;
IServer Server = new RMIServer();
IServer Proxy = (IServer) UnicastRemoteObject.exportObject(Server, ServerPort);
LocateRegistry.createRegistry(RMIPort).rebind("//" + LocalIP + ":" + 
        RMIPort + "/xxx", Proxy);

客戶端:

//Sets the local reference to IServer and creates the IClient
setInstance(new Client(Login, (IServer) LocateRegistry.getRegistry(RemoteIP).
        lookup("//" + RemoteIP + ":" + RMIPort + "/xxx")));
//Gets the IClient and makes it available for the IServer to call notify(...)
Proxy.connect((IClient) (UnicastRemoteObject.exportObject(getInstance(), 0)));

該解決方案在本地可用,但是當我嘗試通過Internet使用它時卻無法使用。

我已經設置了路由器,以將計算機暴露於固定IP地址並轉發1099和1100端口。 此解決方案允許其他開發人員“查找”我的服務器並獲得有效且可用的代理,但不允許他們導出其IClient。 看來JVM試圖將對象導出到其本地網絡,並且執行在此處停止。

所以,我試圖將-Djava.rmi.server.hostname=my-external-IP JVM參數傳遞給我的服務器本地和遠程客戶端。 這樣做,exportObject會向遠程ip而不是本地ip拋出一個ConnectException

算了吧。 通過Internet使用回調需要每個客戶端配置他的防火牆/ NAT盒/無論允許入站連接和可能的端口轉發。 其中許多根本不可配置,其中許多是由網絡管理員運行的,他們不會這樣做。

注意,您還必須在固定端口上導出。

還有另一種選擇:

http://dev.root1.de/projects/simon/wiki#Why-SIMON-is-better-than-

該協議與RMI不兼容,但使用情況幾乎相同。 從RMI更改為SIMON通常並不難。 我聽說用戶切換到SIMON只用了30分鍾。

您可能會考慮使用替代解決方案而不是使用RMI,因為我認為它是專為Intranet應用程序(即本地網絡中的企業應用程序)而非Internet而設計的。

我建議在客戶端和服務器之間使用長時間運行的TCP連接,這樣服務器在任何時候想要回傳它只是將消息推送到此連接。

在這種情況下,啟動連接將始終是客戶端任務。 這與郵件客戶端連接到imap或pop3服務器的方式非常相似。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM