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

Java 当ServerSocket抛出IOException并保持服务器运行时该怎么办,java,networking,sockets,Java,Networking,Sockets,基本上我想创建一个坚如磐石的服务器 while (keepRunning.get()) { try { Socket clientSocket = serverSocket.accept(); ... spawn a new thread to handle the client ... } catch (IOException e) { e.printStackTrace(); // NOW WHAT?

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

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);
            }
        }
    }
}    
while(keepRunning.get()){
试一试{
Socket clientSocket=serverSocket.accept();
…生成一个新线程来处理客户端。。。
bindExceptionCounter=0;
}捕获(IOE异常){
e、 printStackTrace();
重新创建服务器套接字();
}
}
私有void重新创建ServerSocket(){
同时(继续修剪){
试一试{
info(“尝试重新创建服务器套接字”);
ServerSocket socket=ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE\u事件\u服务器\u端口);
//没有引发异常,然后使用新套接字。
serverSocket=socket;
打破
}捕获(绑定异常){
info(“BindException表示服务器套接字仍然良好。”,e);
bindExceptionCounter++;
如果(bindExceptionCounter<5){
打破
}
}捕获(IOE异常){
logger.warn(“重新创建服务器套接字的问题”,e);
e、 printStackTrace();
试一试{
睡眠(30000);
}捕获(中断异常ie){
警告;
}
}
}
}    

确保区分可能收到的不同的
IOException
s。这是创建连接时的例外情况吗?一旦建立了连接,是否属于例外情况

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


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

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


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

如果服务器套接字关闭(由您关闭)或资源(例如文件句柄)用完,您可以在accept()上获得IOException。不管怎样,你都无能为力。如果serverSocket关闭(您可以对此进行测试),您可能有很好的理由这样做。如果资源耗尽,则必须增加资源限制(这需要重新启动应用程序),或者出现资源泄漏

但是,如果服务器套接字仍然是 好吧,那么很遗憾把它关上 杀死所有以前接受的 仍然存在的连接 沟通


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

重新连接-你的意思是再次创建服务器套接字吗?如果创建一个新的服务器套接字,但因BindException而失败-这是否意味着100%确定旧服务器套接字完全正常?我不能肯定地说“是”,但总的来说,我会这么认为。我也会使用防御策略。例如,如果X个失败调用了接受,那么您可能会认为服务器套接字有点损坏,并选择关闭服务器套接字。如何测试套接字是否关闭?我认为serversocket.isClosed()总是返回false,因为较高层不会得到较低层的通知。这是正确的吗?