我有一个客户端通过C Berkeley套接字连接到服务器。我(尝试)通过使用MSG_DONTWAIT和MSG_PEEK调用套接字上的recv()来定期检查连接是否仍然有效。但是,我发现在某些情况下连接断开时(例如,在连接的接口关闭后)以及根本没有数据要读取时,此调用都会返回EAGAIN。因此,我无法使用此方法区分连接是否仍然有效。
这是我的功能:
/* return 1 if still connected, 0 otherwise */
int still_connected()
{
int nbytes_recvd = 0;
char buf[2];
int err;
nbytes_recvd = recv(fd,buf,sizeof(buf),MSG_PEEK|MSG_DONTWAIT);
err = errno;
if ( nbytes_recvd == 0 )
{
return 0;
}
else if ( nbytes_recvd < 0 )
{
if ( (err == ENOTSOCK) ||
(err == ENOTCONN) ||
(err == EINVAL) ||
(err == ECONNREFUSED) ||
(err == EBADF) ||
(err == EOPNOTSUPP) )
{
return -1;
}
}
/* nbytes_recvd > 0 or EAGAIN or EWOULDBLOCK */
/* but I get EAGAIN even if the connection is down because I shut down the interface */
return 1;
}
如何准确检查连接是否仍然有效?
答案 0 :(得分:2)
从TCP连接的两个端点之一的角度来看,已消失的对等体与仍然存在但尚未发送任何数据的对等体之间没有区别。您无法使用recv()
或任何其他方法区分这些情况。
检测对等体是否已关闭,已重置,已消失或已无法访问的唯一方法是发送一些数据并查看会发生什么。有两种选择:
SO_KEEPALIVE
)。这将导致TCP偶尔发送一个keepalive数据包,并期望来自对等体的ACK
。如果对等方无法ACK
,那么您可以了解连接已断开。