Java SocketChannel没有检测到断开连接?

ary*_*axt 5 java sockets socketchannel

我使用选择器运行套接字.我试图检查我的套接字是否连接到服务器.

Boolean connected = _channel.isConnected();
Run Code Online (Sandbox Code Playgroud)

它总是返回true.我关闭了计算机上的机场(互联网连接),当我检查套接字是否已连接时,它仍然返回true.知道为什么吗?我尝试每3秒向服务器写一次数据,但它仍然不会将我的套接字状态更改为断开连接.

irr*_*ble 11

通常,如果关闭操作系统级网络,写入套接字应该抛出异常,因此您知道连接已断开.

但更一般地说,我们无法确定是否已传送数据包.在java(也可能是C)中,无法检查数据包是否已确认.

即使我们可以检查TCP ACK,也不能保证服务器接收处理该数据包.它只表示目标机器接收到数据包并将其缓冲在内存中.之后很多事情都会出错.

所以,如果你真的想确定,你就不能依赖传输协议.您必须具有应用程序级别ACK,即服务器应用程序在收到从客户端处理消息后回写ACK消息.

从客户端的角度来看,它将消息写入服务器,然后尝试从服务器读取ACK.如果它得到它,可以肯定它的消息被接收处理.如果它没有得到确认,那么,它不知道发生了什么.根据经验,很可能TCP失败了.下一个可能性是服务器崩溃了.除了ACK无法到达客户端之外,一切都可能正常.


And*_*s_D 5

可以通过调用connect方法连接套接字通道; 连接后,插座通道保持连接状态,直到它关闭.

由于物理连接中断或服务器故障,当服务器不再可用时,通道不会关闭.因此,一旦建立连接,isConnected()将返回,true直到您关闭通道.

如果要检查,如果服务器仍然可用,则向套接字输出流发送一个字节.如果出现异常,则服务器不可用(连接丢失).


编辑

对于EJP - 一些代码来测试和重新考虑你的评论和答案:

public class ChannelTest {
     public static void main(String[] args) throws UnknownHostException, IOException {
      Socket google = new Socket(InetAddress.getByName("www.google.com"), 80);
      SocketChannel channel = SocketChannel.open(google.getRemoteSocketAddress());
      System.out.println(channel.isConnected());
      channel.close();
      System.out.println(channel.isConnected());
    }
}
Run Code Online (Sandbox Code Playgroud)

我机器上的输出是

true
false
Run Code Online (Sandbox Code Playgroud)

  • 亲爱的downvoters - 如果您认为答案没有帮助,请发表评论.至少EJP评论不正确,因为他的答案......问题是关于SocketChannels,我仍然确定,这解释了,为什么关闭机场不会导致`isConnected()== false`. (2认同)