为什么在没有尝试I / O的情况下检测TCP套接字是否被对等端正常关闭是不可能的?

作为最近一个问题的后续内容,我想知道为什么在没有尝试在TCP套接字上进行读/写操作的情况下,为什么在Java中检测到套接字已被对等端正常关闭?无论是使用前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

...


MYYA
浏览 343回答 3
3回答

SMILET

底层套接字API没有这样的通知。发送TCP堆栈不会发送FIN位,直到最后一个数据包为止,因此在发送应用程序在发送数据之前逻辑上关闭其套接字时可能会缓冲大量数据。同样,因为网络比接收应用程序更快而缓冲的数据(我不知道,也许你通过较慢的连接中继它)对接收者来说可能是重要的,你不希望接收应用程序丢弃它只是因为堆栈已经收到了FIN位。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java