1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

IOCompletionPort: GetQueuedCompletionStatus returns listen socket

Discussion in 'C' started by n8leon, Mar 13, 2008.

  1. n8leon

    n8leon New Member

    Joined:
    Mar 13, 2008
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    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);
    
    
     

Share This Page