使用select()检测套接字何时断开

时间:2013-07-23 18:12:50

标签: c++ c sockets

我正在尝试检测客户端何时与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.
}

1 个答案:

答案 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