Обнаружение при отключении сокета с помощью select()

Я пытаюсь определить, когда клиент был отключен с помощью функции 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 ответов


когда сокет закрывается, он становится "читаемым", но вызывает recv вернет 0 байт. Используя select вы можете сказать, когда сокет можно прочитать, то при чтении его, если recv возвращает 0, тогда вы знаете, что он закрыт.

ваш комментарий "доступные байты" не совсем точен. Сокет может быть считан, однако, если он закрыт, не будет доступных байтов.

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

в неблокирующий сокетов, recv вернет -1 и set errno to EWOULDBLOCK (или EAGAIN), если нет данных и сокет не закрыт.