简体   繁体   English

如何使用Java RMI从服务器向客户端发送消息?

[英]How to send a message from Server to Client using Java RMI?

The application is a Project Management application for a LAN, and it has objects such as Project, Task, etc. So RMI seemed like the way to go. 该应用程序是LAN的项目管理应用程序,它具有项目,任务等对象。因此RMI似乎是要走的路。

But it also has live notifications sent to certain clients as events are triggered by other clients. 但是,当其他客户端触发事件时,它还会向某些客户端发送实时通知。 I read that Servers cannot keep track of the clients that has been connected to it in RMI. 我读到服务器无法跟踪已在RMI中连接到它的客户端。 So as an option I think the server could connect to the client like the client connected to the server beforehand. 因此,作为一个选项,我认为服务器可以像预先连接到服务器的客户端一样连接到客户端。 Is this how it is done? 这是怎么做的?

If not, should I resort to socket programming in this situation? 如果没有,我应该在这种情况下采用套接字编程吗?

Apologies in advance if this is a stupid question. 如果这是一个愚蠢的问题,请提前道歉。

You are right in you assumption. 你是对的。

For active push-style notification from server to clients, the clients have to be "servers" also. 对于从服务器到客户端的主动推送式通知,客户端也必须是“服务器”。

So in the client app you also need to have a remote interface. 因此,在客户端应用程序中,您还需要一个远程接口。 The first time the client connects to the server you pass to it a reference to an instance of the remote interface. 客户端第一次连接到服务器时,会向其传递对远程接口实例的引用。

This object needs to be exported as a remote RMI object, but it doesn't need to be registered in a registry, since you will directly pass a reference to it to the server who needs to call methods on it. 此对象需要导出为远程RMI对象,但不需要在注册表中注册,因为您将直接将对它的引用传递给需要在其上调用方法的服务器。

The server keeps a register of all the clients so it can call back when needed. 服务器保留所有客户端的寄存器,以便在需要时回调。 Typically a Map with the key being a meaningful identifier of the clients and the value being the remote reference to the client. 通常是Map,其中键是客户端的有意义标识符,值是客户端的远程引用。

When the client app is shut down, the client needs to unregister. 关闭客户端应用程序后,客户端需要取消注册。

And the the server will probably want to have a periodic check of all the clients so it doesn't keep references to dead clients. 并且服务器可能希望定期检查所有客户端,因此它不会保留对死客户端的引用。

Your server interface would look something like that : 您的服务器界面看起来像这样:

public interface Server extends Remote {

    void register(Client client) throws RemoteException;

    void unregister(Client client) throws RemoteException;

    void doSomethingUseful(...) throws RemoteException;

    ...

}

And your client interface: 和你的客户端界面:

public interface ClientCallbackInterface extends Remote {

    void ping() throws RemoteException;

    void notifyChanges(...) throws RemoteException;

}

And somewhere in your client app startup code : 在您的客户端应用启动代码的某处:

ClientCallbackInterface client = new ClientImpl();

UnicastRemoteObject.exportObject(client);

Registry registry = LocateRegistry.getRegistry(serverIp, serverRegistryPort); 

Server server = (Server) registry.lookup(serviceName);

server.register(client);

It is totally possible to implement it. 完全可以实现它。 But not trivial. 但不是微不足道的。 There are many things you have to take care of : 你需要照顾很多事情:

  • You must take care of which can be a problem if there are firewalls involved. 如果涉及防火墙,您必须注意哪个可能是一个问题。
  • Could be problems with local OS firewall too, your client app actually must open local incoming ports 也可能是本地OS防火墙的问题,您的客户端应用程序实际上必须打开本地传入端口
  • If you try to start several clients on the same machine you will have port conflict, must take care of that too 如果您尝试在同一台计算机上启动多个客户端,则会发生端口冲突,因此也必须注意这一点
  • Totally not going to work outside of LAN 完全没有在LAN外工作

I did implement a system like this and it works fine. 我确实实现了这样的系统,它工作正常。 But all that said if I had to do it again I would definitely use something else, probably REST services and WebSockets for the callbacks. 但是,如果我不得不再次这样做,我肯定会使用其他东西,可能是REST服务和WebSockets用于回调。 It would be much less constraints on the network part, just HTTP needed. 它对网络部分的限制要少得多,只需要HTTP。

As Pierre Henry's Answer suggest you can implement a call back pattern that uses observer design pattern in RMI. 正如皮埃尔亨利的答案建议你可以实现一个在RMI中使用观察者设计模式的回调模式。


On granular level you can implement socket programming and use Observer design pattern . 在粒度级别上,您可以实现套接字编程并使用Observer design pattern Each client will first register on to the server. 每个客户端将首先注册到服务器。 Server will store them in a data structure and when some event notification is to be sent server will iterate over these registered clients and invoke methods or push notifications to them. 服务器将它们存储在数据结构中,当要发送某些事件通知时,服务器将遍历这些已注册的客户端并调用方法或将通知推送给它们。

Consider using some implementation of JMS (Java messaging service) like Active MQ . 考虑使用像Active MQ这样的JMS (Java messaging service)一些实现。 Your sender will asynchronously listen to a queue. 您的发件人将异步收听队列。 Sender will send the message and a receiver will receive the message. 发件人将发送消息,接收者将收到消息。 If you want all client to receive message use topics instead of queues and there will be publishers and subscribers. 如果您希望所有客户端都接收消息使用主题而不是队列,则会有发布者和订阅者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM