Comme suite à une récente question, je me demande pourquoi il est impossible en Java, sans tenter de lecture/écriture sur un socket TCP, afin de détecter que le socket a été fermée gracieusement par les pairs? Cela semble être le cas indépendamment du fait que l'on utilise le pré-NIO Socket
ou le NIO SocketChannel
.
Quand un pair gracieusement ferme une connexion TCP, les piles TCP sur les deux côtés de la connexion savoir sur le fait. Le côté serveur (celui qui lance la mise à l'arrêt) se termine dans l'état FIN_WAIT2
, tandis que le côté client (celui qui n'est pas explicitement de répondre à l'arrêt) se termine dans l'état CLOSE_WAIT
. Pourquoi n'est-il pas une méthode en Socket
ou SocketChannel
qui permet d'interroger la pile TCP pour voir si la connexion TCP sous-jacente a été résilié? Est-ce que la pile TCP n'a pas à fournir de telles informations d'état? Ou est-ce une décision de conception afin d'éviter un coûteux appel dans le noyau?
Avec l'aide des utilisateurs qui ont déjà posté quelques réponses à cette question, je crois que je vois où le problème peut venir de la. Le côté qui n'est pas explicitement fermer la connexion se termine dans l'état TCP CLOSE_WAIT
ce qui signifie que la connexion est en cours de fermeture et attend du côté de délivrer son propre CLOSE
de l'opération. Je suppose que c'est assez juste qu' isConnected
retours true
et isClosed
retours false
, mais pourquoi n'est-il pas quelque chose comme isClosing
?
Ci-dessous sont les classes de test que l'utilisation de pré-NIO sockets. Mais des résultats identiques sont obtenus à l'aide de NIO.
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);
}
}
Lorsque le test client se connecte au serveur de test, la sortie reste inchangée, même après que le serveur lance la fermeture de la connexion:
connected: true, closed: false
connected: true, closed: false
...