Linux: is there a read or recv from socket with timeout?

CLinuxSocketsTcp

C Problem Overview


How can I try to read data from socket with timeout? I know, select, pselect, poll, has a timeout field, but using of them disables "tcp fast-path" in tcp reno stack.

The only idea I have is to use recv(fd, ..., MSG_DONTWAIT) in a loop

C Solutions


Solution 1 - C

You can use the setsockopt function to set a timeout on receive operations:

> SO_RCVTIMEO > > Sets the timeout value that specifies > the maximum amount of time an input > function waits until it completes. It > accepts a timeval structure with the > number of seconds and microseconds > specifying the limit on how long to > wait for an input operation to > complete. If a receive operation has > blocked for this much time without > receiving additional data, it shall > return with a partial count or errno > set to [EAGAIN] or [EWOULDBLOCK] if no > data is received. The default for this > option is zero, which indicates that a > receive operation shall not time out. > This option takes a timeval structure. > Note that not all implementations > allow this option to be set.

// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
    
// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);

// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

Reportedly on Windows this should be done before calling bind. I have verified by experiment that it can be done either before or after bind on Linux and OS X.

Solution 2 - C

Here's some simple code to add a time out to your recv function using poll in C:

struct pollfd fd;
int ret;

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN;
ret = poll(&fd, 1, 1000); // 1 second for timeout
switch (ret) {
	case -1:
	    // Error
        break;
	case 0:
        // Timeout 
        break;
    default:
        recv(mySocket,buf,sizeof(buf), 0); // get your data
        break;
}

Solution 3 - C

// works also after bind operation for WINDOWS

DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);

Solution 4 - C

Install a handler for SIGALRM, then use alarm() or ualarm() before a regular blocking recv(). If the alarm goes off, the recv() will return an error with errno set to EINTR.

Solution 5 - C

LINUX

struct timeval tv;
tv.tv_sec = 30;        // 30 Secs Timeout
tv.tv_usec = 0;        // Not init'ing this can cause strange errors
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));

WINDOWS

DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));

NOTE: You have put this setting before bind() function call for proper run

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionosgxView Question on Stackoverflow
Solution 1 - CRobert S. BarnesView Answer on Stackoverflow
Solution 2 - CAbdessamad DoughriView Answer on Stackoverflow
Solution 3 - Ccahit beyazView Answer on Stackoverflow
Solution 4 - CcafView Answer on Stackoverflow
Solution 5 - CvivekView Answer on Stackoverflow