Greetings,
this is my first attempt at IOCP, so please forgive me if I am lost in space here...
The Problem: It seems to be almost working, but GetQueuedCompletionStatus is returning the listening socket in the Completion Key instead of the accepting socket.
If I don't add the listening socket to the IOCP, then GetQueuedCompletionStatus doesn't come back at all, even after a client connets to my server.
I have been struggling with this most of the week, and have made very little progress. :-(
Is this a common problem? Something obvious?
If not, here is some sample code - can anybody spot the stupid mistake I must be making?
Is there any way I can examine the internals of the IOCP object to see what it is doing, and possibly how I am using it incorrectly?
TIA,
n8
All error checking and lots of over-head stuff removed for clarity...
CODE
// main:
g_hToTheMainIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
hWorkerThreadPool = CreateThread(0, 0, WorkerThread, (void *)(&i), 0, &nThreadID);
g_theMainListenerSocket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
bind(g_theMainListenerSocket, (sockaddr*)&sinInterface, sizeof(sockaddr));
listen(g_theMainListenerSocket, 5);
CreateIoCompletionPort((HANDLE)g_theMainListenerSocket, g_hToTheMainIocp, (ULONG_PTR)g_theMainListenerSocket, 0);
HANDLE hAcceptThread = CreateThread(0, 0, AcceptThread, (void *)g_theMainListenerSocket, 0, &nThreadID);
// Wait for exit signal
// AcceptThread:
SOCKET clientSocket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
HANDLE hIocp = CreateIoCompletionPort((HANDLE)clientSocket, g_hToTheMainIocp, (ULONG_PTR)clientSocket, 0);
OVERLAPPED ol;
char buf[1024];
int bufLen = sizeof(buf);
DWORD dwBytesRecvd = 0;
memset(&buf, 0, sizeof(buf));
memset(&ol, 0, sizeof(ol));
BOOL bAcceptRes = AcceptEx(
theMainListenerSocket,
clientSocket,
buf,
bufLen - ((sizeof(sockaddr_in) + 16) * 2),
sizeof(sockaddr_in) + 16,
sizeof(sockaddr_in) + 16,
&dwBytesRecvd,
&ol);
// This call returns ERROR_IO_PENDING as expected. :)
Sleep(forever);
// Worker Thread(s):
DWORD dwBytesXferred = 0;
OVERLAPPED* pOl = NULL;
ULONG_PTR cKey = 0;
BOOL bRes = GetQueuedCompletionStatus(
g_hToTheMainIocp,
&dwBytesXferred,
&cKey,
&pOl,
INFINITE);
// THE PROBLEM: When my client connects, this call returns, but ...
// cKey is set to theMainListenerSocket whereas I was expecting/hoping it would be the clientSocket
// Now, these two calls fail with 10057 ("socket not connected")
int err = setsockopt( clientFd,
SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT,
(char *)&g_theMainListenerSocket,
sizeof(g_theMainListenerSocket) );
int nBytesRecvd = WSARecv(clientFd,
pWsaBuf, 1, &dwBytes, &dwFlags, pOl, NULL);