Home > Software design >  Why is SO_RCVTIMEO ignored when applied to a recv() windows socket?
Why is SO_RCVTIMEO ignored when applied to a recv() windows socket?

Time:01-12

I'd like the blocking recv() to abort if no data is read within 5 seconds.

Here's the code to create the socket sock and connect to a server

sock = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0 );
WSAConnect( sock, ptr->ai_addr, sizeof ( struct addrinfo ), NULL, NULL, NULL, NULL )

Before calling recv(), the function setsockopt() is called successfully. However, the recv() remains blocked indefinitely?

DWORD timeout = 5 * 1000;

if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) == SOCKET_ERROR) {
    printf("failed setting socket option GLE %d\n", WSAGetLastError());
    closesocket(sock);
    return INVALID_SOCKET;
}

...
cbRead = recv ( sock, ( CHAR * ) pTemp, cbRemaining, 0 );
...

The only workaround I've found is the following code which calls recv() when there's no socket error or timeout

fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);

struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;

int ret = select(0, &fds, NULL, NULL, &tv);
if (ret == SOCKET_ERROR || ret == 0) {
    printf("TIMEOUT detected on socket=%d ERROR=%d\n", s, ret);
    return FALSE;
}

...
cbRead = recv ( sock, ( CHAR * ) pTemp, cbRemaining, 0 );
...

Question

Is there a reason why using SO_RCVTIMEO is ignored? I'd prefer setting the timeout directly on the socket via setsockopt.

CodePudding user response:

According to the detailed Winsock docs for SO_RCVTIMEO,

If the socket is created using the WSASocket function, then the dwFlags parameter must have the WSA_FLAG_OVERLAPPED attribute set for the timeout to function properly. Otherwise the timeout never takes effect.

The WSASocket() call you show does not specify WSA_FLAG_OVERLAPPED among the flags, so your observation that the receive timeout you specify does not take effect is consistent with the documentation.

Note also that the docs for WSA_FLAG_OVERLAPPED say, among other things,

Most sockets should be created with this flag set.

These details are mostly specific to Winsock. As far as I am aware, POSIX sockets do not have or need an analog of WSA_FLAG_OVERLAPPED.

  • Related