Porting a Winsock application to Linux...select(2) is not as simple as MSDN makes it seem
I'm in the middle of porting bits of a Winsock application to Linux. Luckily when I first wrote the networking bits I had made an effort to write it in a somewhat cross platform manner. As a result, I stuck to select()
, send()
, recv()
, and all the other function calls that Winsock provides that are close to the Berkeley socket interface. Things go pretty smoothly, although for some reason there's this really weird pause when connecting that didn't exist before...
Finally I hit a point where, for some reason, I couldn't establish a connection to the server and it just times out. That's really strange, so I threw good old debug statements all over the place and find out that this select()
call is not doing much of a select:
if (select(0, &rdset, &wtset, &errset, &tv) > 0)
Notice the 0? MSDN states that it is:
nfds
Ignored. The nfds parameter is included only for compatibility with Berkeley sockets.
Then I check the equivalent docs on the Linux side of things:
nfds
is the highest-numbered file descriptor in any of the three sets, plus 1.
Well, if I set nfds
to 0, select()
won't be doing very much selecting! Windows has FD_SETSIZE
at 64 by default, and it ignores nfds
and just checks whatever descriptors are in the fd_set
s that you pass to it. Linux considers sockets and files the same thing, and thus has a much higher FD_SETSIZE
(1024 and 4096 seem to be common). You don't want select()
checking 4096 descriptors, so you set nfds to the highest file descriptor you want it to check, plus one. (As an aside, setting nfds to FD_SETSIZE
is a bad idea.)
if (select(my_socket + 1, &rdset, &wtset, &errset, &tv) > 0)
Where my_socket
is an appropriate file descriptor (such as the one returned by socket()
). This works just fine in Windows too, since it ignores the nfds
parameter.
Armed with this newfound knowledge, I go and fix all the other select()
statements in my code, which ends up fixing the weird pause as well. Effectively, without a proper nfds
value, select()
just acts as a timer and blocks until the specified amount of time has elapsed.