该应用程序是LAN的项目管理应用程序,它有项目,任务等对象。所以RMI似乎是要走的路。
但是,当其他客户端触发事件时,它还会向某些客户端发送实时通知。我读到服务器无法跟踪已在RMI中连接到它的客户端。因此,作为一个选项,我认为服务器可以像预先连接到服务器的客户端一样连接到客户端。这是怎么做的?
如果没有,我应该在这种情况下使用套接字编程吗?
如果这是一个愚蠢的问题,请提前道歉。
答案 0 :(得分:11)
你是对的。
对于从服务器到客户端的主动推送式通知,客户端必须是"服务器"还
因此,在客户端应用程序中,您还需要一个远程接口。客户端第一次连接到服务器时,会向其传递对远程接口实例的引用。
此对象需要作为远程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。
答案 1 :(得分:0)
正如Pierre Henry的回答所建议的那样,你可以实现一个在RMI中使用观察者设计模式的回调模式。
在粒度级别,您可以实现套接字编程并使用Observer design pattern
。每个客户端将首先注册到服务器。服务器将它们存储在数据结构中,当要发送某些事件通知时,服务器将遍历这些已注册的客户端并调用方法或向其发送通知。
考虑使用JMS (Java messaging service)
的某些实现,例如Active MQ
。您的发件人将异步收听队列。发件人将发送消息,接收者将收到消息。如果您希望所有客户端都接收消息使用主题而不是队列,则会有发布者和订阅者。