该应用程序是一个局域网项目管理应用程序,其中包括项目、任务等对象。因此,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。
Client
接口是否扩展了 ClientCallbackInterface
接口? - Aniket Thakur在粒度层面上,您可以实现套接字编程并使用观察者设计模式
。每个客户端将首先注册到服务器。服务器将把它们存储在数据结构中,当需要发送某些事件通知时,服务器将遍历这些已注册的客户端并调用方法或向它们推送通知。
考虑使用一些JMS(Java消息服务)
的实现,如Active MQ
。您的发送方将异步侦听队列。发送方将发送消息,接收方将接收消息。如果您希望所有客户端都接收消息,请改用主题而不是队列,并且将有发布者和订阅者。