4

我在关闭服务器组件时遇到了一些麻烦,希望能得到一些帮助。

我的服务器代码如下所示,它有一个关闭服务器的方法

服务器

    private final String address = "127.0.0.1";
    private Registry registry;
    private int port = 6789;

    public RmiServer() throws RemoteException {
        try {
            registry = LocateRegistry.createRegistry(port);
            registry.rebind("rmiServer", this);
        } catch (RemoteException e) {
            logger.error("Unable to start the server. Exiting the application.", e);
            System.exit(-1);
        }
    }


    public void shutDownServer() throws RemoteException {
        int succesful = 0;
        try {
            registry.unbind("rmiServer");
            UnicastRemoteObject.unexportObject(this, true);
            Thread.sleep(1000);
        } catch (NotBoundException e) {
            logger.error("Error shutting down the server - could not unbind the registry", e);
            succesful = -1;
        } catch (InterruptedException e) {
            logger.info("Unable to sleep when shutting down the server", e);
            succesful = -1;
        }
        catch (AccessException e) {
            logger.info("Access Exception", e);
            succesful = -1;
        }
        catch (UnmarshalException e) {
            System.out.println(e.detail.getMessage());
            logger.info("UnMarshall Exception", e);
            succesful = -1;
        }
        catch (RemoteException e) {
            System.out.println(e.detail.getMessage());
            logger.info("Remote Exception", e);
            succesful = -1;
        }

        logger.info("server shut down gracefully");     
        System.exit(succesful);
}

我的客户端连接正常,没有问题,所以要关闭我创建了一个新应用程序,复制客户端代码进行连接,然后在服务器上调用 close 方法

关闭

公共类关机{

private String serverAddress = "127.0.0.1";
private String serverPort = "6789";
private ReceiveMessageInterface rmiServer;
private Registry registry;

public Shutdown(){
    try {
        registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue());
        rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));
        logger.info("Client started correctly");
        rmiServer.shutDownServer();
        System.exit(0);
    }
    catch (UnmarshalException e ){
        logger.error("Unmarshall exception. Exiting application", e);
        System.exit(-1);
    }
    catch (RemoteException e) {
        logger.error("Remote object exception occured when connecting to server. Exiting application", e);
        System.exit(-1);
    } catch (NotBoundException e) {
        logger.error("Not Bound Exception occured when connecting to server. Exiting application", e);
        System.exit(-1);
    }
}

无论我尝试什么,我都会收到以下异常;

ERROR com.rmi.client.RMIClient - Unmarshall exception. Exiting application
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is: 
    java.net.SocketException: Connection reset
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
    at sun.rmi.server.UnicastRef.invoke(Unknown Source)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
    at $Proxy0.shutDownServer(Unknown Source)
    at com.rmi.shutdown.Shutdown.<init>(Shutdown.java:31)
    at com.rmi.shutdown.Shutdown.main(Shutdown.java:52)
Caused by: java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at java.io.DataInputStream.readByte(Unknown Source)
    ... 7 more

我相信这可能是由于客户端没有正确断开连接而只是被“切断”,但我不确定如何断开服务器端的连接?

请有人建议。

谢谢

4

2 回答 2

5

使用 force = true 取消导出不会中止正在进行的调用。一般来说,它会让正在进行的调用运行到完成。您的shutDownServer方法几乎是正确的,因为它取消注册远程引用并取消导出它。但是,它接下来要做的事情不起作用。首先,它会休眠一秒钟。这使呼叫保持进行,并使客户端等待回复。然后关闭代码退出服务器 JVM,而不从远程调用返回。这会在客户端仍在等待回复时关闭客户端的连接。这就是客户端收到连接重置异常的原因。

要干净地关闭,请注销远程对象,使用 force = true 取消导出它(就像您所做的那样),然后简单地返回。这将向客户端发送回复,使其远程调用完成,然后退出。回到服务器,在最后一个正在进行的调用完成后,如果没有导出其他对象,并且没有其他东西保持 JVM(例如非守护线程),则 JVM 将退出。您需要让 RMI 完成其服务器端处理,而不是调用System.exit().

于 2013-08-12T04:35:49.843 回答
1

The system is doing exactly what you told it to do. You told it to unexport itself, and you set the 'force' parameter to true, which aborts calls in progress, so it unexported itself and aborted the call in progress. Just ignore it, or if you insist on a clean response to the shutdown client, have the server start a new thread for the unexport operation, with a short delay so the shutdown call can return to the client.

于 2013-04-25T22:36:57.123 回答