为什么不尝试 I/O,就不可能检测到 TCP 套接字已被对等方正常关闭?
作为对最近一个问题的跟进,我想知道为什么在Java中,如果不尝试在TCP套接字上读取/写入,就不可能检测到套接字已被对等体优雅地关闭?无论使用前NIO还是NIO,情况似乎都是如此。Socket
SocketChannel
当对等方优雅地关闭 TCP 连接时,连接两端的 TCP 堆栈都知道这一事实。服务器端(启动关机的服务器端)最终处于 状态 ,而客户端(未显式响应关机的服务器端)最终处于状态。为什么在 或 中没有可以查询 TCP 堆栈以查看底层 TCP 连接是否已终止的方法?是 TCP 堆栈不提供此类状态信息吗?还是为了避免对内核进行代价高昂的调用而做出的设计决策?FIN_WAIT2
CLOSE_WAIT
Socket
SocketChannel
在已经发布了这个问题的一些答案的用户的帮助下,我想我看到了问题可能来自哪里。未显式关闭连接的一方最终处于 TCP 状态,这意味着连接正在关闭并等待该端发出自己的操作。我想返回和返回是足够公平的,但是为什么没有这样的东西呢?CLOSE_WAIT
CLOSE
isConnected
true
isClosed
false
isClosing
以下是使用 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
...