Як наступне нещодавнє запитання , мені цікаво, чому неможливо в Java, не намагаючись читати / писати на сокеті TCP, виявити, що сокет був витончено закритий одноранговою ланкою? Здається, це має місце незалежно від того, чи використовується хтось до NIO Socket
або NIO SocketChannel
.
Коли одноранговий зв'язок витончено закриває TCP-з'єднання, стеки TCP з обох сторін з'єднання знають про факт. Серверна сторона (та, яка ініціює вимкнення) опиняється в стані FIN_WAIT2
, тоді як клієнтська сторона (та, яка явно не реагує на вимкнення) опиняється в стані CLOSE_WAIT
. Чому в методі немає Socket
або SocketChannel
який може запросити стек TCP, щоб побачити, чи не було розірвано базове з'єднання TCP? Це те, що стек TCP не надає такої інформації про стан? Або це дизайнерське рішення, щоб уникнути дорогого дзвінка в ядро?
За допомогою користувачів, які вже розмістили деякі відповіді на це питання, я думаю, я бачу, звідки проблема може виникнути. Сторона, яка явно не закриває з'єднання, опиняється в стані TCP, що CLOSE_WAIT
означає, що з'єднання перебуває в стані відключення і чекає, поки сторона видасть власну CLOSE
операцію. Я гадаю, це досить справедливо, що isConnected
повертається true
і isClosed
повертається false
, але чому немає чогось подібного isClosing
?
Нижче наведені тестові класи, які використовують розетки pre-NIO. Але однакові результати отримують за допомогою 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);
}
}
Коли тестовий клієнт підключається до тестового сервера, вихід залишається незмінним навіть після того, як сервер ініціює вимкнення з'єднання:
connected: true, closed: false
connected: true, closed: false
...