1. We have moved from vBulletin to XenForo and you are viewing the site in the middle of the move. Though the functional aspect of everything is working fine, we are still working on other changes including the new design on Xenforo.
    Dismiss Notice

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