Java SocketChannel 没有检测到断开连接?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3484972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java SocketChannel doesn't detect disconnection?
提问by aryaxt
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.
它总是返回true。我关闭了计算机上的 Airport(互联网连接),当我检查套接字是否已连接时,它仍然返回 true。知道为什么吗?我尝试每 3 秒向服务器写入一次数据,但它仍然没有将我的套接字状态更改为断开连接。
回答by irreputable
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.
然而,更普遍的是,我们无法确定数据包是否已送达。在java(也可能是C)中,没有办法检查数据包是否被确认。
Even if we can check TCP ACKs, it doesn't guarantee that the server received orprocessed the packet. It only means that the target machine received the packet and buffered it in memory. Many things can go wrong after that.
即使我们可以检查 TCP ACK,也不能保证服务器收到或处理了数据包。这仅表示目标机器接收到数据包并将其缓存在内存中。在那之后,很多事情都可能出错。
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 andprocessed a message from client.
所以如果你真的想确定,你不能依赖传输协议。您必须具有应用程序级别的 ACK,即服务器应用程序在收到并处理来自客户端的消息后回写一条 ACK 消息。
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 andprocessed. 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.
从客户端的角度来看,它将消息写入服务器,然后尝试从服务器读取 ACK。如果它得到它,就可以确定它的消息被接收和处理。如果它没有得到 ACK,那么它不知道发生了什么。根据经验,很可能 TCP 失败了。下一个可能是服务器崩溃了。也有可能一切正常,除了 ACK 无法到达客户端。
回答by Andreas Dolk
A socket channel can be connected by invoking its connect method; once connected, a socket channel remains connected until it is closed.
可以通过调用其 connect 方法来连接套接字通道;连接后,套接字通道将保持连接状态,直到关闭。
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 returning trueuntil you close the channel on your side.
由于物理连接断开或服务器故障,当服务器不再可用时,通道不会关闭。所以一旦建立了连接,isConnected()就会返回,true直到你关闭你这边的通道。
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:
对于 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());
}
}
Output on my machine is
我机器上的输出是
true
false
回答by user207421
isConnected() tells you whether youhave connected the channelobject, 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 connectionis still there. You can only tell that by using it: -1 from a read, or an exception, tells you that.
isConnected() 告诉您是否已连接您拥有的通道对象,并且没有指定在关闭它后返回 false,尽管显然它确实如此:请参阅 Andreas 的回答。它不是告诉您底层连接是否仍然存在。您只能通过使用它来判断:读取或异常中的 -1 会告诉您这一点。

