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