second FD_READ after recv()

Started by
5 comments, last by remdul 17 years, 9 months ago
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]
Advertisement
I think I understand the question...

I'm pretty sure you need to recreate your 'fd_set' for each call to select().
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
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)?
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.
enum Bool { True, False, FileNotFound };
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?
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().
enum Bool { True, False, FileNotFound };
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.

This topic is closed to new replies.

Advertisement