0

我有一个客户端通过 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;
}

如何准确检查连接是否仍然有效?

4

1 回答 1

2

从 TCP 连接的两个端点之一的角度来看,已经消失的对等点与仍然存在但根本不发送任何数据的对等点之间没有区别。您无法使用recv()或使用任何其他方法来区分这些情况。

检测对等点是否已关闭、已重置、已消失或无法访问的唯一方法是发送一些数据并查看会发生什么。有两种选择:

  • 启用 TCP 保持连接 ( SO_KEEPALIVE)。这将导致 TCP 不时发送一个 keepalive 数据包,并期望ACK来自对等方的数据包。如果对等方失败ACK,那么您可以得知连接已断开。
  • 按照您选择的时间表发送一些实际的应用程序数据(或应用程序级别的保活消息)。类似地,如果对端未能响应此数据(或发送后收到套接字错误),则可以得知连接已断开。
于 2013-04-19T22:10:38.283 回答