Як наступне нещодавнє запитання , мені цікаво, чому неможливо в 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
...