0
votes

I'm trying to set socket options for a client socket returned from the accept() function. But they are not getting set correctly.

My aim is to time out the client after a particular time of inactivity. But the server should still be able to accept other client connections.

Below is my code where I set the socket option. Can you please suggest what is wrong?

while ((new_sock_fd = accept(socket_fd, (struct sockaddr *) &cli_addr, &clilen)) > 0)
{
    if (new_sock_fd < 0)
        printf("Accept Error");
    else
    {
        struct timeval timeout;      
        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        if (setsockopt(new_sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
            error("setsockopt failed\n");
        if (setsockopt(new_sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
            error("setsockopt failed\n");
        pthread_create(&thread, NULL, client_handler, (void *) (intptr_t)new_sock_fd); //intptr_t is big enough to hold the integer prt
    }
}
1
How do you know the options are not being set? Is setsockopt() failing with an error? Does getsocktop() return values you are not expecting? Does the socket simply behave differently than expected? If so, how? What platform is this code running on? On most platforms SO_RCVTIMEO and SO_SENDTIMEO do indeed take a timeval struct as input. But on Windows, they take a DWORD instead. - Remy Lebeau
Also, your Accept Error message will never be reported, since your loop only enters the loop body when new_socket_fd > 0. If you want to do error handling on accept(), you should move it inside the loop instead. - Remy Lebeau

1 Answers

1
votes

My aim is to time out the client after a particular time of inactivity. [...] can you please suggest what when wrong..?

I suspect what's wrong is that you're misunderstanding what SO_RCVTIMEO and SO_SNDTIMEO are intended to do. From the man page:

SO_RCVTIMEO and SO_SNDTIMEO Specify the receiving or sending timeouts until reporting an error. The argument is a struct timeval. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if the socket was specified to be nonblocking. If the timeout is set to zero (the default) then the operation will never timeout.

... but it sounds like what you want is for the TCP connection be automatically closed after a certain amount of time with no traffic on the TCP connection, which is not the same thing as forcing a call to send() or recv() to return after a specified amount of time.

If what you are looking for is a mechanism to close an idle TCP connection, you can implement that yourself by recording the current time whenever data is sent or received on the socket. At a later time (e.g. after send() or recv() times out), you can subtract your recorded last-traffic-seen-at-time from the current time; if the difference is greater than your idle-timeout value, call close() on the socket yourself.