windows套接字多线程I/O完成端口

windows套接字多线程I/O完成端口,windows,multithreading,sockets,Windows,Multithreading,Sockets,我编写了一个带有I/O完成端口的windows socket服务器来处理繁重的数据传输。当只有一个客户端连接时,它可以顺利工作。当多个客户端连接时,其他线程似乎被阻塞,而只有一个线程工作正常 我将设计更改为对每个连接的每个线程使用select(),问题似乎仍然相同。顺便说一句,同样的设计在OSX中也能很好地工作 然而,当我运行多个进程实例时,一个进程为每个连接提供服务,它工作得很好 有人能开导我吗?我仍然喜欢多线程设计。核心代码如下: 代码的其他部分基本上来自: 更新:由于我的服务器应用程序需要

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

我将设计更改为对每个连接的每个线程使用select(),问题似乎仍然相同。顺便说一句,同样的设计在OSX中也能很好地工作

然而,当我运行多个进程实例时,一个进程为每个连接提供服务,它工作得很好

有人能开导我吗?我仍然喜欢多线程设计。核心代码如下:

代码的其他部分基本上来自:


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

欢迎使用SO!为了得到有意义的帮助,请分享你的代码和更具体的问题。你做错了:(Windows上的IOCP工作得很好。你说“其他线程似乎被阻塞了,而只有一个线程工作得很好”…那么你的意思是,除了只有一个线程在处理请求之外,所有的线程都在工作吗?因为这在轻负载下是完全正常的。根据设计,IOCP总是使用尽可能少的线程。谢谢,Harry。事实并非如此。事实是:当两个客户端连接时,一个客户端可能服务得很好,但另一个客户端似乎服务得很好要阻止它应该提供的服务。到目前为止,我仍然没有任何线索。再次感谢。@Luaan-在
GetQueuedCompletionStatus()上阻止I/O处理线程是完全正常的
,这就是IOCP的工作原理。你有一个调用GQCS的线程池,IOCP管理着释放这些线程,以便在完成时为你完成工作。然后,你返回并等待更多的工作。
//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;
}