2009-10-02 24 views
6

Ho un thread del server con questo codice:Come sbloccare un thread bloccato su 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); 
    } 
} 

e un metodo di arresto come questo:

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

voglio che shutdown può sbloccare filo che sono in attesa sulla server.accept() altrimenti deve attendere la connessione prima dello spegnimento del server.

Non riesco a fare server.close() in shutdown() perché devo segnalare al client registrato che il server sta scendendo.

Qualche idea?

risposta

4

Provo a progettare il mio codice in modo che possa essere "arrestato" con un interrupt. Principalmente, questo è dovuto al fatto che il framework Executor nel pacchetto di concorrenza di Java utilizza interrupt per annullare le attività in esecuzione. Inoltre, l'attività "shutdown" non deve conoscere alcuna parte interna dell'attività che viene uccisa.

Tuttavia, una chiamata a accept non risponde ad un interrupt a meno è created from a ServerSocketChannel. Un server creato con un costruttore ServerSocket ignorerà le interruzioni, e non ho trovato un modo per riconfigurare questo.

Se non è possibile modificare il codice che crea il server, predisporre un altro thread per chiamare close sul socket del server. Ciò solleverà un'eccezione nel thread bloccato su accept, indipendentemente dal metodo utilizzato per creare il socket del server.

Questo risulta essere un grande problema quando si utilizza SSL. Un socket JSSE non viene creato da un InterruptibleChannel e non risponderà a un interrupt semplice sul thread.


Ho appena notato che la domanda dice che il server non può essere chiuso senza avvisare il client. L'interruzione riuscita di un socket provoca la sua chiusura.

Su una chiamata a accept questo non dovrebbe essere un problema, poiché il client non è connesso se il socket del server è bloccato in accettare. Questo dovrebbe essere solo un problema per le istanze Socket, che rappresentano le connessioni correnti.

Se ciò non soddisfa i requisiti di notifica, potrebbe essere necessaria una rilavorazione per utilizzare NIO ServerSocketChannel in modalità non bloccante.

+0

mmm buona risposta .. Forse cambio approccio al problema. Gestisco l'arresto del server sul lato client con try-catch. –

0

Hai provato Thread.interrupt()?

Se questa discussione è bloccato in una O operazione/I su un canale interrompibile il canale sarà chiuso, lo stato di interruzione del thread sarà impostato, e il thread riceverà un ClosedByInterruptException.

Se questa discussione è bloccato in un Selettore poi stato di interrupt del thread viene impostata e tornerà immediatamente dall'operazione selezione , eventualmente con uno zero non valore, come se il selettore sveglia metodo sono stati invocati.

+0

Ho provato con this.interrupt(); in shutdown() ma non funziona ... –

+0

Hai bisogno di chiamarlo sul thread che vuoi interrompere (cioè quello bloccato) –

2

Dovresti riuscire a chiudere il socket da un altro thread.

2

Né interrupt (che dipende dai punti di interruzione nello stesso modo in cui la cancellazione dipende dai punti di annullamento) né chiudere lo farà (accept non risponde alla chiusura del descrittore di file). Dovrai comunicare con l'accettazione (prova sendto, con una notifica di arresto) per notificarlo per non continuare ad accettare. Almeno questo è il caso di Linux; non so come sia su altre piattaforme.

+0

come si risolve questo problema alla fine? molte persone dicono che la stretta funzionerà, ma nel mio caso non funziona su Linux. – Djvu

1

Sono stato affrontato per lo stesso problema. Le mie soluzioni di lavoro consistono nel chiudere l'oggetto ServerSocket (serverSocket.close()); facendo ciò, il metodo accept() genera un SocketException, che è ciò che si vuole fare.

Vincent

Problemi correlati