• Advertisement
Sign in to follow this  

second FD_READ after recv()

This topic is 4241 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In my server application I send() data once. Subsequently, I get one FD_READ on the client, recv() and process the data successfully. No problem here. But for unknown reason I then immediately receive another FD_READ again on the client, without the server sending a thing. It is supposed to receive 4 bytes, but the the recv() loop never ends, all I'm getting is SOCKET_ERROR and WSAGetLastError() returns WSAEWOULDBLOCK. With normal (expected) FD_READs these 'errors' are dealt with accordingly (i.e. ignored), but for this unexpected FD_READ I have to do an timeout (break) to avoid infinite loop (there doesn't seem to be any data to receive). My question is, why do I receive a second FD_READ while the server sends nothing? [Edited by - remdul on July 8, 2006 10:38:05 AM]

Share this post


Link to post
Share on other sites
Advertisement
I think I understand the question...

I'm pretty sure you need to recreate your 'fd_set' for each call to select().

Share this post


Link to post
Share on other sites
Could you please elaborate?

I get messages through the window message system (select is called only once on client and server when listening/connecting), I've read about issues with that, could this be the cause of the problem? If so (or not), could you (or anyone else) point me to article/tutorial/code etc. that explains the most efficient way to use Winsock (FYI for a multiplayer fps-like game)?

Share this post


Link to post
Share on other sites
EWOULDBLOCK means that the socket is empty. You should immediately leave the loop if you get that error.

A socket is automatically set to non-blocking when it's entered into an asynchronous select, so EWOULDBLOCK is perfectly expected on occasion in the set-up you describe.

Share this post


Link to post
Share on other sites
Hmm, I thought EWOULDBLOCK indicates that data isn't available right now, and that you have to wait (stay in the loop) until it becomes available, the socket could give you the data right away (blocking socket does the waiting for you) but it WOULD BLOCK?

But that doesn't explain why I'm getting the second FD_READ in the first place, any thoughts on that? What could possibly trigger that?

Share this post


Link to post
Share on other sites
The implementation queues FD_READ events when it sees that there is something in the queue for the socket. You may get these events in your message loop after you've already read the data. Some versions of WinSock even call back your window message proc within your calls to WinSock, leading to some rather convoluted code flow that is hard to get right at times.

In general, you're better off using select() and blocking sockets, rather than asynchronous sockets. On Windows only, you're even better off using I/O completion ports (overlapped I/O on sockets), but that's not portable.

If you stay with asynchronous sockets, then I'd do something like:


bool gotRead = false;
bool gotWrite = false;

while (GetMessage(...)) {
if (!IsDialogMessage(...)) {
TranslateMessage(...);
DispatchMessage(...);
}
if (gotRead) {
gotRead = false;
ReadFromSocket();
}
if (gotWrite) {
gotWrite = false;
WriteToSocket();
}
}

...

WndProc(...) {
switch (msg) {
case FD_READ:
gotRead = true;
break;
case FD_WRITE:
gotWrite = true;
break;
...
}
}


If you have more than one socket, just check all of them inside ReadFromSocket() and WriteToSocket(); they'll be all non-blocking anyway after being passed to AsyncSelect().

Share this post


Link to post
Share on other sites
Thanks. I suspect that the Message system is to blaim, have ruled everything else out. I'll probably go with I/O completion ports, sounds very efficient from what I've read.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement