I'm trying to implement a socket with a recv timeout of 1 Second:
int sockfd;
struct sockaddr_in self;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
ssize_t nBytes;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
self.sin_family = AF_INET;
self.sin_port = htons(PORT);
self.sin_addr.s_addr = INADDR_ANY;
int on = 1;
setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on);
// 1 Sec Timeout
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv);
bind(sockfd, (struct sockaddr*)&self, sizeof(self));
listen(sockfd, 20);
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
nBytes = recv(clientfd, buffer, MAXBUF-1, 0);
Without 'setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv);' the calls to accept and recv work, but recv blocks.
With 'setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv);' the call to accept produces the error 'Resource temporarily unavailable'.
Can somebody please tell me what is wrong with this approach?
Nothing is wrong... The error code EAGAIN (Resource temporarily unavailable) is exactly what you should get after the timeout expires!
You need one more closing parenthesis at each of these two lines.
Try using select() before calling recv() or accept().
select() takes an array of file descriptors (includinig sockets) and returns when at least one of them is ready to receive. It can also return on a timeout.
In linux you can also try poll() (not sure if Winsock provides this).
Which socket do you want to have the one-second timeout on? The one accepting connections, or the one established by accept()?
I'd assume the latter - so try setting the receive timeout on clientfd AFTER the accept returns. You can also get to where you need to be using select, but you shouldn't need to.
This is little bit off topic, but I really want to share this solution to set recv timeout both on windows and unix. Maybe it's me, but it took me a lot of time to figure out why my program doesn't work and how to properly set timeout. Hope you find it useful. It sets timeout to 10 seconds.
For Windows:
For Unix:
For both:
Here's a snippet using
select
: