我有一个套接字正在运行,使用选择器。我正在尝试检查我的套接字是否连接到服务器。
Boolean connected = _channel.isConnected();
它总是返回 true。我在我的电脑上关闭了 Airport(互联网连接),当我检查套接字是否连接时,它仍然返回 true。知道为什么吗?我尝试每 3 秒向服务器写入一次数据,但它仍然没有将我的套接字状态更改为断开连接。
我有一个套接字正在运行,使用选择器。我正在尝试检查我的套接字是否连接到服务器。
Boolean connected = _channel.isConnected();
它总是返回 true。我在我的电脑上关闭了 Airport(互联网连接),当我检查套接字是否连接时,它仍然返回 true。知道为什么吗?我尝试每 3 秒向服务器写入一次数据,但它仍然没有将我的套接字状态更改为断开连接。
通常,如果您关闭操作系统级别的网络,写入套接字应该会引发异常,因此您知道连接已断开。
然而更一般地说,我们不能确定一个数据包是否被传递。在java中(也可能是C),没有办法检查一个数据包是否被确认。
即使我们可以检查 TCP ACK,它也不能保证服务器接收或处理了数据包。这仅意味着目标机器接收到数据包并将其缓冲在内存中。之后很多事情都可能出错。
所以如果你真的想确定,你不能依赖传输协议。您必须具有应用程序级别的 ACK,即服务器应用程序在接收并处理来自客户端的消息后写回 ACK 消息。
从客户端的角度来看,它向服务器写入一条消息,然后尝试从服务器读取 ACK。如果它得到它,则可以确定它的消息已被接收和处理。如果它无法获得 ACK,那么它不知道发生了什么。根据经验,很可能 TCP 失败了。下一个可能性是服务器崩溃了。也有可能一切正常,除了 ACK 无法到达客户端。
可以通过调用其连接方法来连接套接字通道;一旦连接,套接字通道将保持连接状态,直到它关闭。
由于物理连接中断或服务器故障,当服务器不再可用时,通道不会关闭。因此,一旦建立连接,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());
}
}
我机器上的输出是
true
false
isConnected() 告诉您是否已连接您拥有的通道对象,并且未指定在关闭它后返回 false,尽管显然确实如此:请参阅 Andreas 的答案。它不能告诉您底层连接是否仍然存在。您只能通过使用它来告诉您:读取中的 -1 或异常会告诉您。