Firstly the WSAOVERLAPPED
and data buffer that you're declaring on the stack above your call to AcceptEx()
will not be in existence when a completion occurs (unless you are calling GetQueuedCompletionStatus()
in the same function, which would be a trifle odd). You need to dynamically allocate them or pool them.
Secondly you state that you associate the socket to the completion port after you call AcceptEx()
. That's wrong. You need to do these things before you call AcceptEx()
.
- Create a socket with
WSA_FLAG_OVERLAPPED
set. - Bind it to the address you want to listen on.
- Call listen on it with your desired backlog.
- Load
AcceptEx()
dynamically using the listening socket and a call toWSAIoctl
(not strictly necessary and the code you show should work but this way you can be sure you get your listening socket from the same underlying winsock provider and that it supports AcceptEx(). - Load
GetAcceptExSockaddrs()
in the same way as you loadAcceptEx()
- you'll need it once the accept completes. - Associate the listening socket to your IOCP.
Now you can post a number of AcceptEx()
calls using the listening socket and new 'accept' socket which you create like this:
- Create a socket with
WSA_FLAG_OVERLAPPED
set. - Associate the socket to your IOCP.
As stated above you need to ensure that the buffer and the OVERLAPPED are unique per call and last until the completion occurs.
When the completion occurs you have to do the following....
- Call
setsockopt()
withSO_UPDATE_ACCEPT_CONTEXT
on the accepted socket using the listening socket as the data... - Deblock your addresses using
GetAcceptExSockaddrs()
. - Process any data (if you allocated enough space in the buffer for data).
Note that by design AcceptEx()
can be used to accept a new connection and return the initial data from that connection in one operation (this leads to slightly better performance in situations where you know you will always want some data before you can start doing things but is horribly complex to manage if you want to defend aginst the denial of service attack that can be launched simply by connecting and NOT sending data - I wrote about this here).
If you do not want AcceptEx()
to wait for data to arrive then simply provide a data buffer that is ONLY big enough for the addresses to be returned and pass 0 as the 'buffer size'. This will cause the AcceptEx()
to operate like an overlaped accept()
and return as soon as the connection is established.
Note that Martin James' initial comment to your question is in fact the answer you're looking for. Don't pass outBufLen - ((sizeof (sockaddr_in) + 16) * 2)
, pass 0
.