gpt4 book ai didi

c - WSAWaitForMultipleObjects 阻塞除最后一个以外的任何线程

转载 作者:太空宇宙 更新时间:2023-11-04 04:56:28 25 4
gpt4 key购买 nike

我的多线程 SMTP/POP3 服务器有问题。服务器启动一个线程池来处理传入的连接。主线程创建套接字和线程,将套接字作为适当结构中的参数传递。线程的循环函数如下:

SOCKET SMTP_ListenSocket = (SOCKET) data->SMTPconn;
SOCKET POP3_ListenSocket = (SOCKET) data->POP3conn;
static struct sockaddr_in ClntAddr;
unsigned int clntLen = sizeof(ClntAddr);
hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
hEvents[2] = exitEvent; //HANDLE FOR A MANUAL RESET EVENT
WSAEventSelect(SMTP_ListenSocket, hEvents[0], FD_ACCEPT);
WSAEventSelect(POP3_ListenSocket, hEvents[1], FD_ACCEPT);

while(1){

DWORD res = WaitForMultipleObjects(3, hEvents, FALSE, INFINITE);
switch(res){

case WAIT_OBJECT_0: {
ClientSocket = my_accept(SMTP_ListenSocket,(struct sockaddr *) &ClntAddr,&clntLen);
/* ... */
my_shutdown(ClientSocket,2);
my_closesocket(ClientSocket);
ClientSocket = INVALID_SOCKET;
break;
}

case WAIT_OBJECT_0 + 1: {

ClientSocket = my_accept(POP3_ListenSocket,(struct sockaddr *) &ClntAddr,&clntLen);
/* ... */
my_shutdown(ClientSocket,2);
my_closesocket(ClientSocket);
ClientSocket = INVALID_SOCKET;
break;
}

case WAIT_OBJECT_0 + 2:
{
exitHandler(0);
break;
}
}//end switch

}//end while

当池只包含一个线程时,没有问题。当池中包含更多线程时,只有一个线程接受传入连接

最佳答案

您是否让池线程都调用相同的代码?如果是,则不要像这样使用 WaitForMultipleObjects()(或 WSAWaitForMultipleEvents())。这种模型只有在一个线程轮询连接时才能可靠地工作。如果您有多个线程同时进行轮询,那么就会出现竞争条件。

相反,您应该使用具有重叠 I/O 或完成端口的 AcceptEx()。创建套接字的线程可以在每个套接字上调用 AcceptEx() 以对每个套接字进行新操作排队,然后池化线程可以使用 GetQueuedCompletionStatus() GetOverlappedResult() 使挂起的连接出队而不用担心践踏其他线程。接受连接后,接收线程可以根据需要对其进行处理,然后调用 AcceptEx() 为该套接字排队新操作。

关于c - WSAWaitForMultipleObjects 阻塞除最后一个以外的任何线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7168332/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com