我正在尝试检测客户端何时与select()函数断开连接。问题是,我不太了解select()是如何工作的。我正在使用以下代码,你能告诉我我做错了什么和/或如何检测客户端是否断开连接? 我正在使用非阻塞套接字。
int Network::bytesAvailable()
{
long bytes = 0;
if(ioctl(this->sockfd, FIONREAD, &bytes) < 0)
{
printf("ERROR: Network:bytesAvailable: ioctl() call failed.\n");
return -1;
}
return bytes;
}
NetworkStatus Network::status()
{
struct timeval tv;
fd_set fd;
int result = 0;
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(this->sockfd, &fd);
result = select(this->sockfd + 1, &fd, 0, 0, &tv);
if(result && !this->bytesAvailable())
{
return -1; // disconnected, I'm guessing this is definitely WRONG.
}
else if(result > 0 && FD_ISSET(this->sockfd, &fd))
{
return 1; // bytes available.
}
else if(!result)
{
return 0; // timeout
}
return -1; // select() call failed.
}
答案 0 :(得分:9)
当套接字关闭时,它变为“可读”但调用recv
将返回0字节。使用select
,您可以判断何时可以读取套接字,然后在读取时recv
返回0,然后您知道它已关闭。
您的评论“可用字节数”并不完全准确。但是,可以从中读取套接字,如果它已关闭,则不会有可用的字节。
else if(result > 0 && FD_ISSET(this->sockfd, &fd))
{
return 1; // bytes available.
}
在非阻塞套接字中,如果没有数据且套接字未关闭,recv
将返回-1并将errno
设置为EWOULDBLOCK
(或EAGAIN
)