In meinem Hauptthread habe ich eine while(listening)
Schleife, die accept()
mein ServerSocket-Objekt aufruft, dann einen neuen Client-Thread startet und ihn einer Sammlung hinzufügt, wenn ein neuer Client akzeptiert wird.
Ich habe auch einen Admin-Thread, mit dem ich Befehle wie 'exit' ausgeben möchte, wodurch alle Client-Threads heruntergefahren, selbst heruntergefahren und der Haupt-Thread heruntergefahren werden, indem das Abhören auf false eingestellt wird.
Der accept()
Aufruf in der while(listening)
Schleife blockiert jedoch, und es scheint keine Möglichkeit zu geben, ihn zu unterbrechen, sodass die while-Bedingung nicht erneut überprüft werden kann und das Programm nicht beendet werden kann!
Gibt es einen besseren Weg, dies zu tun? Oder eine Möglichkeit, die Blockierungsmethode zu unterbrechen?
quelle
Antworten:
Sie können
close()
von einem anderen Thread aus aufrufen , und deraccept()
Aufruf löst a ausSocketException
.quelle
close()
, ich meine, es wird die Ausnahme auslösen, also gibt es eine andere Möglichkeit (die keine Ausnahme auslöst, auch nicht basierend auf dem Timeout), nicht mehr auf Anfragen zu warten?readLine()
gibt dann null zurück und die normalen Schließvorgänge, die der Thread bereits haben sollte, werden ausgeführt.Wenn Sie das Zeitlimit aktivieren
accept()
, wird die Blockierung nach der angegebenen Zeit durch den Anruf zeitlich begrenzt:http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT
quelle
Ist das Aufrufen
close()
derServerSocket
Option?http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29
quelle
Sie können einfach einen "void" -Socket für break serversocket.accept () erstellen.
Serverseite
Methode zum Unterbrechen des Serverzyklus
quelle
Der Grund für die
ServerSocket.close()
Auslösung einer Ausnahme ist , dass an diesen Socket einoutputstream
oder eininputstream
Socket angeschlossen ist. Sie können diese Ausnahme sicher vermeiden, indem Sie zuerst die Eingabe- und Ausgabestreams schließen. Versuchen Sie dann, das zu schließenServerSocket
. Hier ist ein Beispiel:Sie können diese Methode aufrufen, um jeden Socket von überall zu schließen, ohne eine Ausnahme zu erhalten.
quelle
ServerSocket
sondern an ein angehängt,Socket
und wir sprechen über das Schließen desServerSocket
nicht dasSocket
, sodass dasServerSocket
geschlossen werden kann, ohne dieSocket
Streams von a zu schließen.Verwenden Sie serverSocket.setSoTimeout (timeoutInMillis) .
quelle
OK, ich habe das so funktioniert, dass die Frage des OP direkter angesprochen wird.
Lesen Sie weiter über die kurze Antwort hinaus, um ein Thread-Beispiel zu erhalten, wie ich dies verwende.
Kurze Antwort:
Beispiel aus der realen Welt:
In diesem Beispiel wartet ein ServerSocket auf eine Verbindung innerhalb eines Threads. Wenn ich die App schließe, möchte ich den Thread (genauer gesagt den Socket) auf saubere Weise herunterfahren, bevor ich die App schließen lasse. Daher verwende ich .setSoTimeout () auf dem ServerSocket und verwende dann den ausgelösten Interrupt Nach dem Timeout überprüfen Sie, ob das übergeordnete Element versucht, den Thread herunterzufahren. Wenn ja, dann setze ich den Socket schließen, setze dann ein Flag, das anzeigt, dass der Thread fertig ist, und breche dann aus der Threads-Schleife aus, die eine Null zurückgibt.
Dann, in meiner Controller-Klasse ... (Ich zeige nur relevanten Code, massiere ihn nach Bedarf in deinen eigenen Code)
Ich hoffe, das hilft jemandem auf der Straße.
quelle
Eine andere Sache, die Sie versuchen können, um sauberer zu sein, besteht darin, ein Flag in der Accept-Schleife zu überprüfen. Wenn Ihr Admin-Thread dann die Thread-Blockierung auf dem Accept beenden möchte, setzen Sie das Flag (machen Sie es thread-sicher) und erstellen Sie dann einen Client-Socket Anschluss an die Abhörbuchse. Das Akzeptieren hört auf zu blockieren und gibt den neuen Socket zurück. Sie können ein einfaches Protokoll ausarbeiten, das dem Listening-Thread sagt, dass er den Thread sauber beenden soll. Schließen Sie dann den Socket auf der Clientseite. Keine Ausnahmen, viel sauberer.
quelle