7

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

1 回答 1

11

当一个套接字关闭时,它变得“可读”,但调用recv将返回 0 个字节。使用select您可以知道何时可以读取套接字,然后在读取它时如果recv返回 0 则您知道它已关闭。

您的评论“可用字节数”并不完全准确。但是,可以从中读取套接字,如果它关闭,将没有可用的字节。

else if(result > 0 && FD_ISSET(this->sockfd, &fd))
{
    return 1; // bytes available.
}

在非阻塞套接字中,如果没有数据且套接字未关闭,recv将返回 -1 并设置errnoEWOULDBLOCK(或)。EAGAIN

于 2013-07-23T18:19:45.237 回答