windows socket多线程I / O完成端口

时间:2014-04-13 05:38:08

标签: windows multithreading sockets

我写了一个带有I / O完成端口的Windows套接字服务器来处理大量数据传输。当只连接一个客户端时,它可以顺利运行。当多个客户端连接时,其他线程似乎被阻塞,而只有一个线程工作正常。

我改变了我的设计,使用select()和每个连接的每个线程,问题似乎仍然相同。顺便说一句,相同的设计在OSX中运行良好。

但是,当我运行我的进程的多个实例时,一个进程为每个连接提供服务,它运行良好。

任何人都可以开导我吗?我还是喜欢多线程设计。核心代码如下:

代码的其他部分基本上来自:http://www.codeproject.com/Articles/13382/A-simple-application-using-I-O-Completion-Ports-an

//Worker thread will service IOCP requests
DWORD WINAPI WorkerThread(LPVOID lpParam)
{    
    int nThreadNo = (int)lpParam;

    void *lpContext = NULL;
    OVERLAPPED       *pOverlapped = NULL;
    CClientContext   *pClientContext = NULL;
    DWORD            dwBytesTransfered = 0;
    int nBytesRecv = 0;
    int nBytesSent = 0;
    DWORD             dwBytes = 0, dwFlags = 0;

    //Worker thread will be around to process requests, until a Shutdown event is not Signaled.
    while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
    {
        BOOL bReturn = GetQueuedCompletionStatus(
            g_hIOCompletionPort,
            &dwBytesTransfered,
            (LPDWORD)&lpContext,
            &pOverlapped,
            INFINITE);

        //WriteToConsole("\nThread %d: GetQueuedCompletionStatus.", nThreadNo);


        if (NULL == lpContext)
        {
            //We are shutting down
            break;
        }

        //Get the client context
        pClientContext = (CClientContext *)lpContext;

        if ((FALSE == bReturn) || ((TRUE == bReturn) && (0 == dwBytesTransfered)))
        {
            //Client connection gone, remove it.
            RemoveFromClientListAndFreeMemory(pClientContext);
            continue;
        }

        WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
        OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();

        switch (pClientContext->GetOpCode())
        {
        case OP_READ:
            pClientContext->SetTransLen(dwBytesTransfered);
            if(!pClientContext->IsComplete())
            {
                pClientContext->SetOpCode(OP_READ);

                dwFlags = 0;

                //Overlapped send
                nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1, 
                    &dwBytes, dwFlags, p_ol, NULL);

                WriteToConsole("\nThread %d: WSASend continue bytes = %d.", nThreadNo, dwBytes);

                if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
                {
                    //Let's not work with this client
                    RemoveFromClientListAndFreeMemory(pClientContext);

                    WriteToConsole("\nThread %d: WSASend failed.", nThreadNo);
                }
            }
            else
            {
                WriteToConsole("\nsocket %d: WSASend complete.", pClientContext->GetSocket());

                //clear cache
                pClientContext->ResetWSABUF();

                //for the next recv, must be triggered.
                pClientContext->SetOpCode(OP_WRITE);
                //Get the data.
                nBytesRecv = WSARecv(pClientContext->GetSocket(), p_wbuf, 1, 
                    &dwBytes, &dwFlags, p_ol, NULL);

                if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
                {
                    WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);

                    //Let's not work with this client
                    RemoveFromClientListAndFreeMemory(pClientContext);
                }
            }

            break;

        case OP_WRITE:
            pClientContext->SetTransLen(dwBytesTransfered);
            if(pClientContext->IsComplete())
            {
                if(!pClientContext->ProcessCmd())
                {
                    WriteToConsole("\nThread %d: ProcessCmd failed.", nThreadNo);
                    //Let's not work with this client
                    RemoveFromClientListAndFreeMemory(pClientContext);
                }

                WriteToConsole("\nThread %d: receive completed.", nThreadNo);

                //Send the message back to the client.
                pClientContext->SetOpCode(OP_READ);

                dwFlags = 0;

                //Overlapped send
                nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1, 
                    &dwBytes, dwFlags, p_ol, NULL);

                WriteToConsole("\nThread %d: WSASend bytes = %d.", nThreadNo, dwBytes);

                if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
                {
                    WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);

                    //Let's not work with this client
                    RemoveFromClientListAndFreeMemory(pClientContext);
                }
            }
            else    //continue receiving
            {
                pClientContext->SetOpCode(OP_WRITE);
                //Get the data.
                nBytesRecv = WSARecv(pClientContext->GetSocket(), p_wbuf, 1, 
                    &dwBytes, &dwFlags, p_ol, NULL);

                WriteToConsole("\nThread %d: WSARecv continue bytes = %d.", nThreadNo, dwBytes);

                if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
                {
                    WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);

                    //Let's not work with this client
                    RemoveFromClientListAndFreeMemory(pClientContext);
                }
            }




            break;

        default:
            //We should never be reaching here, under normal circumstances.
            break;
        } // switch
    } // while

    return 0;
}

更新:由于我的服务器应用程序需要向多个客户端发送大量数据,它可能工作正常几分钟,但不知何故,某些线程只是阻止而没有响应。它与数据大小有关吗?

0 个答案:

没有答案