问题
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 anACK
from the peer. If the peer fails toACK
, 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