我有一个 RMI 服务器,许多客户端连接到该服务器。当客户端注册更改时,服务器会做出反应并指示所有客户端进行更改。
我一直在研究许多 hello world RMI 示例,但没有一个解决如何从服务器持久连接回客户端。
我想要实现的是这些方面:服务器在 rmiregistry 上注册。客户端 1 连接到服务器并调用服务器上的方法。客户端 2 连接到服务器并调用服务器上的方法。服务器将更改从 client2 发送到 client1。
如果不将每个客户端都注册为服务器,如何实现这一点?
编辑:看了几个优秀的答案(更平坦)后,我遇到了以下异常 java.rmi.StubNotFoundException: Stub class not found: thegame.connectivity.GameClient_Stub; 嵌套异常是:
java.lang.ClassNotFoundException: thegame.connectivity.GameClient_Stub
at sun.rmi.server.Util.createStub(Util.java:292)
at sun.rmi.server.Util.createProxy(Util.java:140)
at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:196)
at java.rmi.server.UnicastRemoteObject.exportObject(UnicastRemoteObject.java:310)
at java.rmi.server.UnicastRemoteObject.exportObject(UnicastRemoteObject.java:237)
at thegame.connectivity.GameClient.bind(GameClient.java:37)
at thegame.connectivity.GameClient.run(GameClient.java:51)
at thegame.connectivity.GameClient.main(GameClient.java:29)
Caused by: java.lang.ClassNotFoundException: thegame.connectivity.GameClient_Stub
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at sun.rmi.server.Util.createStub(Util.java:286)
... 7 more
在这堂课上
public class GameClient extends Thread implements Remote, Client, ModelChangeListener<Client>{
private static final long serialVersionUID = -394039736555035873L;
protected Queue<GameModelEvent> queue = new ConcurrentLinkedQueue<GameModelEvent>();
public GameClient(){
}
public static void main(String[] args){
GameClient client = new GameClient();
client.run();
}
protected void bind(){
System.setProperty("java.rmi.server.codebase","file:bin/");
try {
Registry registry = LocateRegistry.getRegistry();
Client c = (Client)UnicastRemoteObject.exportObject(this);
Server stub = (Server) registry.lookup("Server");
stub.registerClient(c);
} catch (RemoteException | NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
bind();
while(!Thread.interrupted()){
System.out.print(".");
GameModelEvent event = queue.poll();
while(event != null){
System.out.println(event);
event = queue.poll();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
}
}
...
当我注释掉 UnicatRemoteObject 并仅将 null 作为参数传递时,它运行良好。所以有一个连接,一切都在运行。但是没有存根......注释掉代码库也没有效果。代码库在服务器上运行良好。
关于什么是错的任何想法?