2010-06-12 27 views
5

基本上我想创建一个坚如磐石的服务器。当ServerSocket抛出IOException并保持服务器运行时该怎么办

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); 
      } 
     } 
    } 
}  

回答

4

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

一般来说,客户端还应该假设连接将被打破,重新连接是必要的。换句话说,这不仅仅是服务器必须强大 - 客户端还应该预测连接错误并重新连接。

+0

如果创建一个新的服务器套接字(该套接字由于BindException而失败) - 这是否意味着100%确定旧服务器套接字完全正常? – s5804 2010-06-12 11:59:55

+0

我不能肯定地说“是”,但总的来说,我会假设。我也会使用防守策略。例如。如果您接到X个失败的呼叫,那么您可能会认为服务器套接字不知何故中断,并选择关闭服务器套接字。 – mdma 2010-06-12 12:38:41

1

确保您区分可能会收到的不同IOException。这是创建连接的例外吗?一旦连接已经建立,它是一个例外吗?

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

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

+0

重新连接 - 你的意思是再次创建服务器套接字? – s5804 2010-06-12 11:56:52

+0

如果您丢失了套接字,那么是的... – 2010-06-12 13:20:49

1

如果服务器套接字已关闭(由您)或您用尽资源(例如,),则可以在accept()上获得IOException。文件句柄。无论哪种方式,对此你都无能为力。如果serverSocket关闭(你可以测试这个),你可能有一个很好的理由来做到这一点。如果资源耗尽,您将不得不增加资源限制,这需要重新启动应用程序,否则资源泄漏。

+0

如何测试套接字是否关闭?我认为serversocket.isClosed()总是返回false,因为较高层不会被较低级别通知。它是否正确? – s5804 2010-06-12 12:06:00

1

但是,如果该服务器套接字仍然 OK,那么很可惜,关闭它, 杀死所有以前接受 连接仍在 通信。

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

相关问题