2009-10-02 29 views
6

que tienen un hilo servidor con este código:¿Cómo desbloquear un hilo bloqueado en ServerSocket.accept()?

public void run() { 
    try { 
     ServerSocket server; 
     EneaLog.printLog("Server is running."); 
     server = new ServerSocket(this.portnumber); 

     while (true) { 
      new EneaServerConnection(server.accept(), this.project,stopped).start(); 
      if (stopped) { 
       EneaLog.printLog("Server safe-shutdown completed."); 
       EneaLog.printLog("Hi!"); 
       server.close(); 
       return; 
      } 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex); 
     project.getExceptionHandler().handler(ex); 
    } 
} 

y un método de apagado como esto:

public void shutdown() { 
    EneaLog.printLog("Server shutdown NOW!"); 
    stopped = true; 
} 

Quiero que el cierre puede desbloquear hilo que están esperando en server.accept() de lo contrario, debe esperar la conexión antes del cierre del servidor.

No puedo hacer server.close() en shutdown() porque debo indicarle al cliente registrado que el servidor está bajando.

¿Alguna idea?

Respuesta

4

Intento diseñar mi código para que pueda ser "apagado" con una interrupción. Principalmente, esto se debe a que el marco Executor en el paquete de simultaneidad de Java usa interrupt para cancelar las tareas en ejecución. Además, la tarea de "apagado" no tiene que conocer ninguna parte interna de la tarea que se está matando.

Sin embargo, una llamada a accept no responderá a una interrupción menos es created from a ServerSocketChannel. Un servidor creado con un constructor ServerSocket hará caso de interrupciones, y no he encontrado una manera de volver a configurar esto.

Si no puede cambiar el código que crea el servidor, haga arreglos para que otro hilo llame al close en el socket del servidor. Esto también generará una excepción en el hilo bloqueado en accept, independientemente del método utilizado para crear el socket del servidor.

Esto resulta ser un gran problema cuando se usa SSL. Un socket JSSE no se crea desde un InterruptibleChannel, y no responderá a una interrupción simple en el hilo.


Acabo de notar que la pregunta dice que el servidor no se puede cerrar sin notificar al cliente. Interrumpir con éxito un socket da como resultado su cierre.

En una llamada al accept esto no debería ser un problema, ya que el cliente no está conectado si el socket del servidor está bloqueado en aceptar. Eso solo debería ser un problema para las instancias Socket, que representan las conexiones actuales.

Si eso no satisface los requisitos de notificación, puede ser necesario volver a trabajar para usar el ServerSocketChannel de NIO en modo no bloqueante.

+0

mmm buena respuesta .. Tal vez puedo cambiar el enfoque a un problema. Administro el cierre del servidor en el lado del cliente con try-catch. –

0

¿Has probado Thread.interrupt()?

Si este hilo se bloquea en un/O operación de E sobre un canal interrumpible entonces el canal será cerrado, de estado de interrupción de la rosca se establecerá, y el hilo se recibir un ClosedByInterruptException.

Si este hilo se bloquea en un selector entonces estado de alarma del hilo se puede ajustar y volverá inmediatamente de la operación de selección , posiblemente con un cero no valor, como si del selector de despertar método fue invocado.

+0

He intentado con this.interrupt(); en la parada() pero no funciona ... –

+0

Es necesario llamarlo en la rosca desea interrumpir (es decir, el bloqueado uno) –

2

Usted debe ser capaz de cerrar la toma de otro hilo.

2

Ni la interrupción (eso depende de los puntos de interrupción de la misma forma en que la cancelación depende de los puntos de cancelación) ni la clausura lo hará (accept no responde al cierre de su descriptor de archivo). Tendrá que comunicarse con accept (try sendto, con una notificación de cierre) para notificarle que no continúe aceptando. Al menos este es el caso de Linux; no sé cómo es en otras plataformas.

+0

¿cómo resuelves este problema al fin? muchas personas dicen cerca va a funcionar, pero no funciona en mi caso, que se ejecuta en Linux. – Djvu

1

que he tenido que hacer frente al mismo problema. Mi solución de trabajo consiste en cerrar el objeto ServerSocket (serverSocket.close()); al hacer esto, el método accept() lanzará SocketException, que es lo que desea hacer.

Vincent

Cuestiones relacionadas