远程关闭 RMI 服务器时我遇到一些问题。在我的程序中,客户端需要连接到 RMI 中间件服务器,RMI 中间件连接到 3 个不同的 RMI 服务器(flightManager、carManager 和 roomManager)。客户端可以向中间件提交关闭命令。然后中间件应该关闭 3 个服务器及其自身。但是在我关闭 carManager 后,中间件立即关闭并让另外 2 个服务器保持 Activity 状态。
中间件连接3个管理器并接收3个管理器的 stub ,当它收到关闭调用时,它会执行以下功能:
public void shutdown() throws RemoteException{
try{
this.carManager.shutdown();
this.flightManager.shutdown();
this.roomManager.shutdown();
UnicastRemoteObject.unexportObject(this, true);
System.out.println("Server exiting.");
}
catch(Exception e){}
System.exit(0);
}
这是 3 个不同管理器的代码,它扩展了 ResourceManger 并为中间件提供了一个 stub 作为 IResourceManager。
public class RMIResourceManager extends ResourceManager
{
private static String s_serverName = "Server";
private static String s_rmiPrefix = "test";
public static void main(String args[])
{
if (args.length > 0)
{
s_serverName = args[0];
}
// Create the RMI server entry
try {
// Create a new Server object
RMIResourceManager server = new RMIResourceManager(s_serverName);
// Dynamically generate the stub (client proxy)
IResourceManager resourceManager = (IResourceManager)UnicastRemoteObject.exportObject(server, 0);
// Bind the remote object's stub in the registry
Registry l_registry;
try {
l_registry = LocateRegistry.createRegistry(1099);
} catch (RemoteException e) {
l_registry = LocateRegistry.getRegistry(1099);
}
final Registry registry = l_registry;
registry.rebind(s_rmiPrefix + s_serverName, resourceManager);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
registry.unbind(s_rmiPrefix + s_serverName);
System.out.println("'" + s_serverName + "' resource manager unbound");
}
catch(Exception e) {
System.err.println((char)27 + "[31;1mServer exception: " + (char)27 + "[0mUncaught exception");
e.printStackTrace();
}
}
});
System.out.println("'" + s_serverName + "' resource manager server ready and bound to '" + s_rmiPrefix + s_serverName + "'");
}
catch (Exception e) {
System.err.println((char)27 + "[31;1mServer exception: " + (char)27 + "[0mUncaught exception");
e.printStackTrace();
System.exit(1);
}
// Create and install a security manager
if (System.getSecurityManager() == null)
{
System.setSecurityManager(new SecurityManager());
}
}
public RMIResourceManager(String name)
{
super(name);
}
}
最后还有一个 ResourceManager 类实现了 IResourceManager。里面有关机功能。
public class ResourceManager implements IResourceManager{
public void shutdown() throws RemoteException{
System.exit(1);
}
}
看来管理器的任何终止都会导致中间件的终止。中间件中的关闭函数执行“this.carManager.shutdown();”行并且永远不要执行上面的行。我该如何处理这个问题?
如图所示问题:客户端输入“shutdown”。然后 carManager 关闭,中间件立即关闭。 FlightManager 和 roomManager 保持 Activity 状态。
最佳答案
我认为你的问题是你的 shutdown() 实现实际上在与客户端交互的过程中关闭了服务器 - 因此客户端 stub 看到连接断开,因此抛出一个异常(你在您的屏幕截图) - 在尝试关闭其他两个客户端之前,它会中止该客户端。
您可能希望实现您的服务器,以便在调用 shutdown() 时取消注册该服务器(因此不再接受任何客户端连接),然后启动一个延迟线程来实际关闭应用程序 - 这样,您所在的调用将正常返回给客户端,然后客户端可以继续。
或者,我想您可以将对 shutdown() 的三个调用中的每一个包装在 try/catch 中,这样您就可以忽略每个客户端将抛出的异常并继续告诉下一个服务器关闭...
关于java - 关闭 RMI 服务器时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53165679/