Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/forums/c/)
-   -   IOCompletionPort: GetQueuedCompletionStatus returns listen socket (http://www.go4expert.com/forums/iocompletionport-t9333/)

n8leon 14Mar2008 04:36

IOCompletionPort: GetQueuedCompletionStatus returns listen socket
 
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);



All times are GMT +5.5. The time now is 03:54.