How do I properly determine if my client is still connected to the server with C sockets?

微笑、不失礼 提交于 2019-12-25 01:50:03

问题


I have a client connected to a server via C Berkeley sockets. I (try to) periodically check to see if the connection is still valid by calling recv() on the socket with MSG_DONTWAIT and MSG_PEEK. However, I'm finding that this call returns EAGAIN both when the connection is down in some cases (e.g., after the connection's interface is shut down) and when there is simply no data to read. Hence, there is no way for me to distinguish whether the connection is still valid or not using this method.

Here's my function:

/* 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;
}

How can I accurately check whether the connection is still valid?


回答1:


From the point of view of one of the two endpoints of a TCP connection, there is no difference between a peer that had disappeared and a peer that is still present but simply isn't sending any data. You can't distinguish these situations with recv() or with any other method.

The only way to detect if a peer is down, has reset, has disappeared, or has become unreachable, is to send some data and see what happens. There are two options:

  • Enable TCP keepalives (SO_KEEPALIVE). This will cause TCP to send a keepalive packet once in a while and expect an ACK from the peer. If the peer fails to ACK, then you can learn that the connection has been broken.
  • Send some actual application data (or an application-level keepalive message) on a schedule of your choice. Similarily, if the peer fails to respond to this data (or you get a socket error after sending it), you can learn that the connection has been broken.


来源:https://stackoverflow.com/questions/16113539/how-do-i-properly-determine-if-my-client-is-still-connected-to-the-server-with-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!