Overlapped IO sockets sending and receiving at the same time
-
I'm writing some port forwarding code and don't have control over the size of the data being sent/received. So I need to always have a recv queued even though I may possible be in the middle of a write (since my overlapped sockets are reading and writing to and from each other whenever recv gets new data on either side). How do I allow for the possibility that an unblocked worker thread could be processing a read or a write? IOW how do I know if GetQueuedCompletionStatus was unblocked for a pending WSARecv or WSASend? thanks. ---jt
-
I'm writing some port forwarding code and don't have control over the size of the data being sent/received. So I need to always have a recv queued even though I may possible be in the middle of a write (since my overlapped sockets are reading and writing to and from each other whenever recv gets new data on either side). How do I allow for the possibility that an unblocked worker thread could be processing a read or a write? IOW how do I know if GetQueuedCompletionStatus was unblocked for a pending WSARecv or WSASend? thanks. ---jt
I would do it by using separate event handles for the read and the write, and then inspecting the return value from your wait function to see which event handle was signaled. EDIT ========== OK, I see what you're doing. You're polling GetQueuedCompletionStatus, right? Well that's not the optimum model to use with completion ports, as you see. You're much better off using the OVERLAPPED structure when you call WSARecv and WSASend, and then seeing which event handle is signaled. Here's the pseudo code:
ORecv = new OVERLAPPED struct;
Set ORecv's event handle to your Recv event;
call WSARecv with ORecv;OSend = new OVERLAPPED struct;
Set OSend's event handle to your Send event;
call WSASend with OSend;Wait on the two handles;
See which handle was signalled,
and then call GetQueuedCompletionStatus;The difficult we do right away... ...the impossible takes slightly longer.
-
I would do it by using separate event handles for the read and the write, and then inspecting the return value from your wait function to see which event handle was signaled. EDIT ========== OK, I see what you're doing. You're polling GetQueuedCompletionStatus, right? Well that's not the optimum model to use with completion ports, as you see. You're much better off using the OVERLAPPED structure when you call WSARecv and WSASend, and then seeing which event handle is signaled. Here's the pseudo code:
ORecv = new OVERLAPPED struct;
Set ORecv's event handle to your Recv event;
call WSARecv with ORecv;OSend = new OVERLAPPED struct;
Set OSend's event handle to your Send event;
call WSASend with OSend;Wait on the two handles;
See which handle was signalled,
and then call GetQueuedCompletionStatus;The difficult we do right away... ...the impossible takes slightly longer.
-
Thanks. I'm not polling, I am using the overlapped structure in send and recv but hadn't thought to use separate structures for send versus recv. That should work...thanks.
I personally don't like the idea of waiting on OVERLAPPED handles. I'd much rather not introduce more (or any) synchronization objects to the IOCP handler threads but instead let the IOCP do its magic with all threads waiting on GetQueuedCompletionStatus. I take advantage of the fact that the same overlapped structure pointer you pass to an overlapped function will be returned to you so I use extended OVERLAPPED structures like the one in this article[^]
typedef struct _OVERLAPPEDPLUS {
OVERLAPPED ol;
SOCKET s, sclient;
int OpCode;
WSABUF wbuf;
DWORD dwBytes, dwFlags;
// other useful information
} OVERLAPPEDPLUS;The opcode can be used to indicate read or write (and many other things including non-I/O tasks you want to queue on the IOCP). Also gives you a handy place to keep buffers associated with the operation.
Mark Salsbery :java:
-
I personally don't like the idea of waiting on OVERLAPPED handles. I'd much rather not introduce more (or any) synchronization objects to the IOCP handler threads but instead let the IOCP do its magic with all threads waiting on GetQueuedCompletionStatus. I take advantage of the fact that the same overlapped structure pointer you pass to an overlapped function will be returned to you so I use extended OVERLAPPED structures like the one in this article[^]
typedef struct _OVERLAPPEDPLUS {
OVERLAPPED ol;
SOCKET s, sclient;
int OpCode;
WSABUF wbuf;
DWORD dwBytes, dwFlags;
// other useful information
} OVERLAPPEDPLUS;The opcode can be used to indicate read or write (and many other things including non-I/O tasks you want to queue on the IOCP). Also gives you a handy place to keep buffers associated with the operation.
Mark Salsbery :java:
Wow. That's a great tip. Thanks for sharing!
The difficult we do right away... ...the impossible takes slightly longer.