2010-06-12 8 views
5

Básicamente quiero crear un servidor sólido como una roca.Qué hacer cuando ServerSocket lanza IOException y mantiene el servidor en ejecución

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

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

En el bloque IOException, ¿qué hacer? ¿El socket del servidor está en falta por lo que debe ser recreado? Por ejemplo, espere unos segundos y luego

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

Sin embargo, si el socket del servidor todavía está bien, entonces es una lástima para cerrarla y matar a todas las conexiones previamente aceptadas que todavía se están comunicando.

EDITAR: Después de algunas respuestas, aquí mi intento de tratar con la IOException. ¿Garantizaría la implementación mantener el servidor y solo volver a crear el socket del servidor cuando sea necesario?

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

Respuesta

4

En caso de duda, podría intentar volver a crear el socket del servidor, utilizando el mismo puerto. Si el socket se ha cerrado, la creación tendrá éxito y podrá seguir procesando nuevas conexiones. Las conexiones antiguas se han ido, pero eso está fuera de tu control desde que se cerró el socket. Si el socket no se cerró, la creación de una nueva instancia fallará ya que el puerto todavía está en uso, lo cual puede ignorar, es decir, no reemplazar la referencia del socket del servidor actual.

En general, los clientes también deben suponer que las conexiones se romperán y que es necesaria la reconexión. En otras palabras, no solo el servidor debe ser robusto: los clientes también deben anticipar los errores de conexión y reconectarse.

+0

Si crea un nuevo socket de servidor, que falla con BindException, ¿significará esto que está 100% seguro de que el antiguo socket del servidor está completamente bien? – s5804

+0

No puedo decir "sí" con seguridad, pero en general supongo que sí. También usaría una estrategia defensiva. P.ej. si obtiene el número X de fallas llamando aceptar, entonces puede considerar que el socket del servidor está roto de alguna manera, y elegir cerrar el socket del servidor. – mdma

1

Asegúrese de diferenciar los distintos IOException s que se pueden recibir. ¿Es una excepción al crear una conexión? ¿Es una excepción una vez que se ha establecido una conexión?

El único código que ha proporcionado es accept() ing. En términos generales, un IOException generalmente significa un error en cualquier capa en la red física.

Probablemente el mejor comportamiento alternativo que puede implementar es esperar un cierto tiempo de quantum, y luego tratar de volver a conectar. Supongamos que posiblemente no podrá volver a conectarse, ya que ha perdido la conexión de red por más de un período temporal. Asegúrate de manejar esto con gracia. Como mencionó @mdma, esto también debe ser respaldado por sus clientes.

+0

reconexión - ¿Quiere decir volver a crear el socket del servidor? – s5804

+0

Si perdió el zócalo, entonces sí ... –

1

Puede obtener una IOException en un accept() si el socket del servidor está cerrado (usted) o si se le agotan los recursos, p. manejadores de archivos De cualquier manera, no hay mucho que puedas hacer al respecto. Si el serverSocket está cerrado (puedes probar esto) probablemente tengas una buena razón para hacer esto. Si se le agotan los recursos, tendrá que aumentar su límite de recursos, lo que requiere un reinicio de su aplicación, o si tiene una fuga de recursos.

+0

¿Cómo probar si el socket está cerrado? Pensé que serversocket.isClosed() siempre devuelve falso, porque la capa superior no recibe notificaciones de los niveles inferiores. ¿Es esto correcto? – s5804

1

Sin embargo, si el socket del servidor sigue siendo OK, entonces es una lástima para cerrarla y matar a todos aceptaron previamente conexiones que todavía están comunicación.

Tenga en cuenta que al cerrar el socket del servidor NO se cerrarán las conexiones previamente aceptadas. Tan pronto como una conexión ha sido aceptada, vive una vida separada y alegre en un puerto diferente.

Cuestiones relacionadas