second FD_READ after recv()
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]
I think I understand the question...
I'm pretty sure you need to recreate your 'fd_set' for each call to select().
I'm pretty sure you need to recreate your 'fd_set' for each call to select().
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)?
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.
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.
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?
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:
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().
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().
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement