6 Stimmen

Wie hebt man die Blockierung eines Threads auf, der durch ServerSocket.accept() blockiert ist?

Ich habe einen Server-Thread mit diesem Code:

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

und eine Abschaltmethode wie diese:

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

Ich möchte, dass Shutdown Thread freigeben kann, die auf server.accept() warten, sonst muss ich für die Verbindung vor dem Server-Shutdown warten.

Ich kann server.close() in shutdown() nicht ausführen, weil ich dem registrierten Client signalisieren muss, dass der Server heruntergefahren wird.

Irgendwelche Ideen?

4voto

erickson Punkte 256579

Ich versuche, meinen Code so zu gestalten, dass er mit einem Interrupt "abgeschaltet" werden kann. Hauptsächlich liegt das daran, dass die Executor Framework im Java-Paket für Gleichzeitigkeit verwendet interrupt um laufende Aufgaben abzubrechen. Außerdem muss die "Shutdown"-Aufgabe keine Interna der Aufgabe kennen, die beendet wird.

Allerdings ist ein Anruf bei accept reagiert nicht auf eine Unterbrechung es sei denn, es ist [erstellt aus einer ServerSocketChannel .](http://java.sun.com/javase/6/docs/api/java/nio/channels/ServerSocketChannel.html#socket()) Ein Server, der mit einer ServerSocket Konstruktor ignoriert Unterbrechungen, und ich habe keine Möglichkeit gefunden, dies neu zu konfigurieren.

Wenn Sie den Code, der den Server erstellt, nicht ändern können, sorgen Sie dafür, dass ein anderer Thread die close auf dem Server-Socket. Dies löst auch eine Ausnahme in einem blockierten Thread auf accept unabhängig von der Methode, die zur Erstellung des Server-Sockets verwendet wird.

Dies erweist sich bei der Verwendung von SSL als sehr lästig. Ein JSSE-Socket wird nicht aus einer InterruptibleChannel und antwortet nicht auf eine einfache Unterbrechung des Themas.


Mir ist gerade aufgefallen, dass in der Frage steht, dass der Server nicht geschlossen werden kann, ohne den Client zu benachrichtigen. Die erfolgreiche Unterbrechung eines Sockets führt zu dessen Schließung.

Bei einem Anruf bei accept sollte dies kein Problem sein, da der Client nicht verbunden ist, wenn der Server-Socket in accept blockiert ist. Das sollte nur ein Problem sein für Socket Instanzen, die aktuelle Verbindungen darstellen.

Wenn dies den Anforderungen an die Benachrichtigung nicht genügt, kann eine Überarbeitung zur Verwendung von NIOs ServerSocketChannel im nicht-sperrenden Modus erforderlich sein.

2voto

Tom Hawtin - tackline Punkte 142461

Sie sollten in der Lage sein, den Socket von einem anderen Thread aus zu schließen.

2voto

Jade Punkte 21

Weder interrupt (das von Interrupt-Punkten abhängt, so wie cancellation von cancellation-Punkten abhängt) noch close werden es tun (accept reagiert nicht auf das Schließen seines Dateideskriptors). Sie müssen mit accept kommunizieren (versuchen Sie sendto, mit einer Benachrichtigung zum Herunterfahren), um ihm mitzuteilen, dass er nicht weiter akzeptieren soll. Zumindest ist dies der Fall auf Linux; ich weiß nicht, wie es auf anderen Plattformen ist.

1voto

vwiencek Punkte 31

Ich stehe vor dem gleichen Problem. Meine Lösungen bestehen darin, das ServerSocket-Objekt zu schließen (serverSocket.close()); dies führt dazu, dass die accept()-Methode eine SocketException auslöst, und das ist es, was Sie tun wollen.

Vincent

0voto

Brian Agnew Punkte 260470

Haben Sie versucht Thread.interrupt() ?

Wenn dieser Thread in einer E/A blockiert ist Operation auf einem unterbrechbaren Kanal blockiert wird, wird der Kanal geschlossen, der Interrupt-Status des Threads des Threads wird gesetzt, und der Thread erhält eine ClosedByInterruptException.

Wenn dieser Thread in einer Selektor blockiert, wird der Interrupt-Status des Threads Status des Threads gesetzt und er gibt sofort von der Auswahl Operation zurück, möglicherweise mit einem von Null verschiedenen Wert zurück, genauso wie wenn der Selektor Wakeup-Methode des Selektors aufgerufen würde.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X