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 theWSA_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
.