Java SocketChannel 未检测到断开连接?
我有一个正在运行的套接字,使用选择器。我正在尝试检查我的套接字是否已连接到服务器。
Boolean connected = _channel.isConnected();
并且它总是返回 true。我关闭了计算机上的机场(互联网连接),当我检查套接字是否已连接时,它仍然返回 true。 知道为什么吗? 我尝试每 3 秒向服务器写入一次数据,但它仍然没有将我的套接字状态更改为断开连接。
I have a socket running, using selectors. I am trying to check to see if my socket is connected to the server or not.
Boolean connected = _channel.isConnected();
and it always returns true. I turned off Airport (internet connection) on my computer, and when i check to see if the socket is connected or not, it still returns true.
Any idea why?
I try to write data to the server every 3 seconds, and it still doesn't change the state of my socket to disconnected.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
通常,如果您关闭操作系统级网络,写入套接字应该会抛出异常,因此您知道连接已损坏。
但更一般地说,我们无法确定数据包是否已送达。在java(可能也是C)中,没有办法检查数据包是否已被ACK。
即使我们可以检查 TCP ACK,它也不能保证服务器已收到或处理了数据包。它仅意味着目标机器收到了数据包并将其缓冲在内存中。此后很多事情可能会出错。
因此,如果您真的想确定,则不能依赖传输协议。您必须具有应用程序级ACK,即服务器应用程序在接收并处理来自客户端的消息后写回ACK 消息。
从客户端的角度来看,它向服务器写入一条消息,然后尝试从服务器读取 ACK。如果它得到它,则可以确定它的消息已被接收并被处理。如果它无法获得 ACK,那么它就不知道发生了什么。根据经验,TCP 很可能失败。下一个可能是服务器崩溃了。也有可能一切顺利,只是 ACK 无法到达客户端。
Usually if you turn off OS level networking, writes to socket should throw exceptions, so you know the connection is broken.
However more generally, we cann't be sure if a packet is delivered. In java (probably C too), there is no way to check if a packet is ACK'ed.
Even if we can check TCP ACKs, it doesn't guarantee that the server received or processed the packet. It only means that the target machine received the packet and buffered it in memory. Many things can go wrong after that.
So if you really want to sure, you can't rely on transport protocol. You must have application level ACK, that is, the server application writes back an ACK message after it received and processed a message from client.
From client point of view, it writes a message to server, then tries to read ACK from server. If it gets it, it can be certain that its message is received and processed. If it fails to get ACK, well, it has no idea what has happened. Empirically, most likely TCP failed. Next possiblity is that server crashed. It's also possible that everything went OK, except the ACK couldn't reach the client.
当服务器由于物理连接断开或服务器故障而不再可用时,通道不会关闭。因此,一旦建立连接,
isConnected()
将返回true
,直到您关闭您这边的通道。如果您想检查服务器是否仍然可用,请向套接字输出流发送一个字节。如果出现异常,则服务器不可用(连接丢失)。
编辑
EJP - 一些代码来测试和重新考虑您的评论和答案:
我的机器上的输出是
The channel is not closed when the server is not available anymore, due to a broken physical connection or a server failure. So once a connection has been established,
isConnected()
will be returningtrue
until you close the channel on your side.If you want to check, if the server is still available, send a byte to the sockets outputstream. If you get an Exception, then the server is unavailable (connection lost).
Edit
for EJP - some code to test and reconsider your comment and answer:
Output on my machine is
isConnected() 告诉您是否您已连接您拥有的channel对象,并且未指定在您关闭它后返回 false,尽管显然它确实如此:请参阅 Andreas 的回答。它不会告诉您底层连接是否仍然存在。你只能通过使用它来告诉你:-1 来自读取或异常,告诉你这一点。
isConnected() tells you whether you have connected the channel object, which you have, and it's not specified to return false after you close it, although apparently it does: see Andreas's answer. It's not there to tell you whether the underlying connection is still there. You can only tell that by using it: -1 from a read, or an exception, tells you that.