如何正确确定我的客户端是否仍然使用C套接字连接到服务器?

时间:2013-04-19 21:10:07

标签: c sockets tcp network-programming

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

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

1 个答案:

答案 0 :(得分:2)

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

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

  • 启用TCP keepalive(SO_KEEPALIVE)。这将导致TCP偶尔发送一个keepalive数据包,并期望来自对等体的ACK。如果对等方无法ACK,那么您可以了解连接已断开。
  • 根据您选择的计划发送一些实际的应用程序数据(或应用程序级别的保持活动消息)。类似地,如果对等方无法响应此数据(或者在发送之后出现套接字错误),则可以了解连接已断开。