当 ServerSocket 抛出 IOException 并保持服务器运行时该怎么办

发布于 2024-09-05 13:51:03 字数 1818 浏览 6 评论 0原文

基本上我想创建一个坚如磐石的服务器。

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
    } catch (IOException e) {
        e.printStackTrace();
        // NOW WHAT?
    }
}

在IOException块中,做什么?服务器套接字是否有故障,需要重新创建?例如,等待几秒钟,然后

serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT);

但是,如果服务器套接字仍然正常,那么很遗憾关闭它并杀死所有先前接受的仍在通信的连接。

编辑:经过一些回答后,我尝试处理 IOException。该实现是否可以保证服务器保持正常运行并且仅在必要时重新创建服务器套接字?

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
        bindExceptionCounter = 0;
    } catch (IOException e) {
        e.printStackTrace();

        recreateServerSocket();
    }
}

private void recreateServerSocket() {
    while (keepRunning) {
        try {
            logger.info("Try to re-create Server Socket");
            ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT);

            // No exception thrown, then use the new socket.
            serverSocket = socket;
            break;
        } catch (BindException e) {
            logger.info("BindException indicates that the server socket is still good.", e);
            bindExceptionCounter++;

            if (bindExceptionCounter < 5) {
                break;
            }
        } catch (IOException e) {
            logger.warn("Problem to re-create Server Socket", e);
            e.printStackTrace();

            try {
                Thread.sleep(30000);
            } catch (InterruptedException ie) {
                logger.warn(ie);
            }
        }
    }
}    

Basically I want to create a rock solid server.

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
    } catch (IOException e) {
        e.printStackTrace();
        // NOW WHAT?
    }
}

In the IOException block, what to do? Is the Server socket at fault so it need to be recreated? For example wait a few seconds and then

serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT);

However if the server socket is still OK, then it is a pity to close it and kill all previously accepted connections that are still communicating.

EDIT: After some answers, here my attempt to deal with the IOException. Would the implementation be guaranteeing keeping the server up and only re-create server socket when only necessary?

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
        bindExceptionCounter = 0;
    } catch (IOException e) {
        e.printStackTrace();

        recreateServerSocket();
    }
}

private void recreateServerSocket() {
    while (keepRunning) {
        try {
            logger.info("Try to re-create Server Socket");
            ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT);

            // No exception thrown, then use the new socket.
            serverSocket = socket;
            break;
        } catch (BindException e) {
            logger.info("BindException indicates that the server socket is still good.", e);
            bindExceptionCounter++;

            if (bindExceptionCounter < 5) {
                break;
            }
        } catch (IOException e) {
            logger.warn("Problem to re-create Server Socket", e);
            e.printStackTrace();

            try {
                Thread.sleep(30000);
            } catch (InterruptedException ie) {
                logger.warn(ie);
            }
        }
    }
}    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

漫雪独思 2024-09-12 13:51:26

但是如果服务器套接字仍然
好吧,那么关闭就可惜了
杀死所有先前接受的
仍然存在的连接
沟通。

请注意,关闭服务器套接字不会关闭之前接受的连接。一旦连接被接受,它就会在不同的港口过着独立、快乐的生活。

However if the server socket is still
OK, then it is a pity to close it and
kill all previously accepted
connections that are still
communicating.

Please note that closing the server socket will NOT close previously accepted connections. As soon as a connection has been accepted it lives a separate, joyful life at a different port.

木緿 2024-09-12 13:51:21

确保区分可能收到的不同 IOException。创建连接时是否有异常?连接建立后是否存在异常?

您提供的唯一代码是用于 accept()ing。一般来说,IOException通常意味着物理网络上任何层的错误。

您可以实现的最佳后备行为可能是等待一定的时间段,然后尝试重新连接。假设您很可能无法重新连接,因为您失去网络连接的时间超过了暂时的时间。确保你优雅地处理这件事。正如 @mdma 提到的,这也必须得到您的客户的支持。

Make sure you differentiate between different IOExceptions you might receive. Is it an exception on creating a connection? Is it an exception once a connection has already been established?

The only code you gave is for accept()ing. Generally speaking, an IOException usually means an error on any layer on the physical network.

Probably the best fallback behavior you can implement is to wait for a certain time quantum, and then try to reconnect. Assume you most possibly will not be able to reconnect, since you have lost network connection for more than a temporary period. Make sure you handle this gracefully. As @mdma mentioned, this must be supported by your clients as well.

你的笑 2024-09-12 13:51:17

如果服务器套接字(由您)关闭或者您耗尽了资源(例如文件句柄),您可能会在accept() 上收到IOException。不管怎样,你对此无能为力。如果 serverSocket 已关闭(您可以对此进行测试),您可能有充分的理由这样做。如果资源耗尽,您要么必须增加资源限制(这需要重新启动应用程序),要么会发生资源泄漏。

You can get an IOException on an accept() if the server socket is closed (by you) or you run out of resources, e.g. file handles. Either way, there is not much you can do about it. If the serverSocket is closed (you can test for this) you probably had a good reason to do this. If you run out of resources, you will either have to increase your resource limit, which requires a restart of your application, or you have a resource leak.

电影里的梦 2024-09-12 13:51:11

如果有疑问,您可以尝试使用相同的端口重新创建服务器套接字。如果套接字已关闭,则创建将成功,您可以继续处理新连接。旧的连接已经消失,但由于套接字已关闭,因此这超出了您的控制范围。如果套接字未关闭,则创建新实例将失败,因为该端口仍在使用中,您可以忽略它 - 即不要替换当前服务器套接字引用。

一般来说,客户端还应该假设连接将被断开并且需要重新连接。换句话说,不仅仅是服务器必须强大 - 客户端还应该预见到连接错误并重新连接。

If in doubt, you could try re-creating the server socket, using the same port. If the socket has been closed, then the creation will succeed and you can continue processing new connections. The old connections are gone, but that's outside of your control since the socket was closed. If the socket was not closed, then creating a new instance will fail since the port is still in use, which you can just ignore - i.e. don't replace the current server socket reference.

In general, clients should also assume that connections will be broken and that reconnection is necessary. In other words, it's not just the server that has to be robust - clients should also anticipate connection errors and reconnect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文