Advertisement

Overlapper IO - completes immediately, but still calls callback

Started by February 07, 2006 07:39 AM
6 comments, last by Anon Mike 19 years ago
Hi. I started using overlapped IO from Winsock2. I'm sending a block of data by WSASend, speciffying a callback function, like that:
// suppose we got this
WSABUF wsaBuf;
WSAOVERLAPPED overlapped;
DWORD bytesToSend;
DWORD flags;
LPWSAOVERLAPPED_COMPLETION_ROUTINE  pMyCallbackFunc;

// and I use it in:
const int res = WSASend(aSocket, &wsaBuf, 1, &bytesToSend,
                        flags, &overlapped, pMyCallbackFunc;
if (res == SOCKET_ERROR) {
   const int err = WSAGetLastError();
   if (err != WSA_IO_PENDING) {
      printf("FAILURE: WSASend failed! (err=%d)\n", err);
      return false;
   };
   return true;
} else {
   printf("WSASend completed immediately! (%d bytes sent)\n", bytesToSend);
   return on_already_sent();
};

Pretty straightforward. Now, I suppose when the call returns with immediate completion, the callback function wouldn't be called. But it is. What am I doing wrong? Or is this how it is supposed to work? (But I doubt it, since if that was the case, what good would be the immediate completion anyway?)
From MSDN's reference on WSASend() (emphasis mine):
Quote:
If no error occurs and the send operation has completed immediately, WSASend returns zero. In this case, the completion routine will have already been scheduled to be called once the calling thread is in the alertable state.
Advertisement
Thanks, I must have gone blind (as usual), since I've been reading that MSDN page over and over again[grin].

But now, I would have to ignore one from two things: either the immediate success, or the later callback routine call. Otherwise all would mess up a bit.
I guess I have no way to distinguish the real callback from a fake one. So the only thing I could do is to ignore the fact, that the routine completed immediately.

Am I right?
(I know, it doesn't sound too good...)
It's not a "fake" callback... You should probably just handle everything in the callback for consistency and only handle errors in-line. It would make the code simpler as well.
-Mike
Quote:
Original post by Anon Mike
It's not a "fake" callback... You should probably just handle everything in the callback for consistency and only handle errors in-line. It would make the code simpler as well.


If I ignored successfull immediate return from WSARecv call (for consistency), then it is not fake.
But if I got data from WSARecv immediately,
and already processed it,
and maybe reused the buffer, WSABUF and WSAOVERLAPPED for another call to WSARecv
or even just deleted the buffer
then it is not only fake, but can also be dangerous.

(If only I could distinguish between real and fake callbacks, eh)

On the other hand, if I'm willing to handle everything in callbacks, I will be forced to call SleepEx() every time I receive something, by which I would be giving up my time slices, brrr. Well, I guess if I make the receiving buffer big enough, it won't be so bad...
It sounds like you don't really want to use overlapped IO at all but just plain non-blocking IO. Then you don't need to worry about callbacks or alertable wait states. You could also do the ever-popular "network thread" approach but that probably would cause more trouble than it saves.
-Mike
Advertisement
What do you mean by "plain non-blocking IO"? IO thread with a large select?
Maybe...
Normally when you first create a socket it is in blocking mode. If you call recv and there is no data it will sit there and wait until data is available. However you can call ioctlsocket (ioctl on *nix) and pass it FIONBIO to turn on non-blocking mode. Now if you call recv and no data is available it will return immediately and tell you that no data is available and you can go on with your business.

On the client you probably only have one socket so you can just poll it every frame or so. If you have multiple sockets to worry about use select with a timeout of 0.

It is not strictly necessary to use a dedicated thread for this stuff although many do for various reasons.
-Mike

This topic is closed to new replies.

Advertisement