Als Antwort auf eine aktuelle Frage frage ich mich, warum es in Java unmöglich ist, ohne den Versuch, auf einem TCP-Socket zu lesen / schreiben, festzustellen, dass der Socket vom Peer ordnungsgemäß geschlossen wurde. Dies scheint unabhängig davon der Fall zu sein, ob man das Pre-NIO Socket
oder das NIO verwendet SocketChannel
.
Wenn ein Peer eine TCP-Verbindung ordnungsgemäß schließt, wissen die TCP-Stapel auf beiden Seiten der Verbindung Bescheid. Die Serverseite (die das Herunterfahren initiiert) befindet sich im Status FIN_WAIT2
, während die Clientseite (die nicht explizit auf das Herunterfahren reagiert) im Status endet CLOSE_WAIT
. Warum gibt es nicht ein Verfahren in Socket
oder SocketChannel
dass der TCP - Stack abfragen können , um zu sehen , ob die zugrunde liegende TCP - Verbindung beendet wurde? Ist es so, dass der TCP-Stack solche Statusinformationen nicht bereitstellt? Oder ist es eine Entwurfsentscheidung, einen kostspieligen Aufruf des Kernels zu vermeiden?
Mit Hilfe der Benutzer, die bereits einige Antworten auf diese Frage gepostet haben, sehe ich, woher das Problem kommen könnte. Die Seite, die die Verbindung nicht explizit schließt, befindet sich im TCP-Status. Dies CLOSE_WAIT
bedeutet, dass die Verbindung gerade heruntergefahren wird und darauf wartet, dass die Seite ihren eigenen CLOSE
Vorgang ausführt. Ich , dass es fair genug nehme an, dass isConnected
Erträge true
und isClosed
Renditen false
, aber warum nicht , wie es etwas gibt isClosing
?
Nachfolgend sind die Testklassen aufgeführt, die Pre-NIO-Sockets verwenden. Mit NIO werden jedoch identische Ergebnisse erzielt.
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(12345);
final Socket cs = ss.accept();
System.out.println("Accepted connection");
Thread.sleep(5000);
cs.close();
System.out.println("Closed connection");
ss.close();
Thread.sleep(100000);
}
}
import java.net.Socket;
public class MyClient {
public static void main(String[] args) throws Exception {
final Socket s = new Socket("localhost", 12345);
for (int i = 0; i < 10; i++) {
System.out.println("connected: " + s.isConnected() +
", closed: " + s.isClosed());
Thread.sleep(1000);
}
Thread.sleep(100000);
}
}
Wenn der Testclient eine Verbindung zum Testserver herstellt, bleibt die Ausgabe unverändert, auch nachdem der Server das Herunterfahren der Verbindung initiiert hat:
connected: true, closed: false
connected: true, closed: false
...
Socket.close
ist kein anmutiger Abschluss.