关闭RMI服务器时出现的问题

时间:2018-11-06 04:18:43

标签: java rmi

远程关闭RMI服务器时遇到一些麻烦。在我的程序中,客户端需要连接到RMI中间件服务器,并且RMI中间件连接到3个不同的RMI服务器(flightManager,carManager和roomManager)。客户端可以向中间件提交关闭命令。然后,中间件应关闭3台服务器及其本身。但是,在我关闭carManager之后,中间件立即关闭,并使另外2台服务器保持活动状态。

中间件连接3个管理器并接收3个管理器的存根,当它收到关闭调用时,它将执行以下功能:

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并将中间件作为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();”行。绝不执行以上行。我该如何解决这个问题?

图片显示了问题:客户端输入“关机”。然后,carManager关闭,并且中间件立即关闭。 flightManager和roomManager保持活动状态。 enter image description here

1 个答案:

答案 0 :(得分:1)

我认为您的问题是您的shutdown()实现实际上在与客户端进行交互的过程中关闭了服务器-因此客户端存根会看到连接断开,并因此引发异常(您在屏幕截图)-在尝试关闭其他两个客户端之前中止该客户端。

您希望实现服务器,以便在调用shutdown()时取消注册该服务器(这样就不再接受任何客户端连接),然后启动一个延迟线程来实际关闭应用程序-这样,您正在进行的呼叫将正常返回给客户,然后客户可以继续。

或者,我想您可以在try / catch中包装对shutdown()的三个调用中的每一个,因此您可以忽略每个客户端将抛出并继续告诉下一个服务器关闭的异常... < / p>