![](/img/trans.png)
[英]RMI chat program in java - how to send mesage from client to client (not through the server)?
[英]How to send a message from Server to Client using Java RMI?
該應用程序是LAN的項目管理應用程序,它具有項目,任務等對象。因此RMI似乎是要走的路。
但是,當其他客戶端觸發事件時,它還會向某些客戶端發送實時通知。 我讀到服務器無法跟蹤已在RMI中連接到它的客戶端。 因此,作為一個選項,我認為服務器可以像預先連接到服務器的客戶端一樣連接到客戶端。 這是怎么做的?
如果沒有,我應該在這種情況下采用套接字編程嗎?
如果這是一個愚蠢的問題,請提前道歉。
你是對的。
對於從服務器到客戶端的主動推送式通知,客戶端也必須是“服務器”。
因此,在客戶端應用程序中,您還需要一個遠程接口。 客戶端第一次連接到服務器時,會向其傳遞對遠程接口實例的引用。
此對象需要導出為遠程RMI對象,但不需要在注冊表中注冊,因為您將直接將對它的引用傳遞給需要在其上調用方法的服務器。
服務器保留所有客戶端的寄存器,以便在需要時回調。 通常是Map,其中鍵是客戶端的有意義標識符,值是客戶端的遠程引用。
關閉客戶端應用程序后,客戶端需要取消注冊。
並且服務器可能希望定期檢查所有客戶端,因此它不會保留對死客戶端的引用。
您的服務器界面看起來像這樣:
public interface Server extends Remote {
void register(Client client) throws RemoteException;
void unregister(Client client) throws RemoteException;
void doSomethingUseful(...) throws RemoteException;
...
}
和你的客戶端界面:
public interface ClientCallbackInterface extends Remote {
void ping() throws RemoteException;
void notifyChanges(...) throws RemoteException;
}
在您的客戶端應用啟動代碼的某處:
ClientCallbackInterface client = new ClientImpl();
UnicastRemoteObject.exportObject(client);
Registry registry = LocateRegistry.getRegistry(serverIp, serverRegistryPort);
Server server = (Server) registry.lookup(serviceName);
server.register(client);
完全可以實現它。 但不是微不足道的。 你需要照顧很多事情:
我確實實現了這樣的系統,它工作正常。 但是,如果我不得不再次這樣做,我肯定會使用其他東西,可能是REST
服務和WebSockets
用於回調。 它對網絡部分的限制要少得多,只需要HTTP。
正如皮埃爾亨利的答案建議你可以實現一個在RMI中使用觀察者設計模式的回調模式。
在粒度級別上,您可以實現套接字編程並使用Observer design pattern
。 每個客戶端將首先注冊到服務器。 服務器將它們存儲在數據結構中,當要發送某些事件通知時,服務器將遍歷這些已注冊的客戶端並調用方法或將通知推送給它們。
考慮使用像Active MQ
這樣的JMS (Java messaging service)
一些實現。 您的發件人將異步收聽隊列。 發件人將發送消息,接收者將收到消息。 如果您希望所有客戶端都接收消息使用主題而不是隊列,則會有發布者和訂閱者。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.