Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting whenever socket disconnected using select()

Tags:

c++

c

sockets

I'm trying to detect whenever client has been disconnected with select() function. The problem is that, I don't quite much understood how select() does work. I'm using following code, can you tell me what I'm doing wrong and/or how to detect if client is disconnected? I'm using non-blocking sockets.

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.
}
like image 826
user2399415 Avatar asked Jul 23 '13 18:07

user2399415


1 Answers

When a socket closes it becomes "readable" but calling recv will return 0 bytes. Using select you can tell when the socket can be read then when reading it if recv returns 0 then you know it has closed.

Your comment "bytes available" isn't exactly accurate. The socket may be read from however, if it is closed there will be no bytes available.

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

In non-blocking sockets, recv will return -1 and set errno to EWOULDBLOCK (or EAGAIN) if there is no data and the socket is not closed.

like image 151
Dave Rager Avatar answered Oct 09 '22 15:10

Dave Rager