gpt4 book ai didi

c++ - Winsock 接受事件有时会停止发出信号 (WSAEventSelect)

转载 作者:可可西里 更新时间:2023-11-01 11:04:44 26 4
gpt4 key购买 nike

我对属于多线程套接字服务器的一段遗留 c++/winsock 代码有疑问。该应用程序创建一个线程来处理来自客户端的连接,通常一次有几百个连接。它通常可以毫无问题地运行数天(连续),然后突然停止接受连接。这只发生在生产中,从不测试。

它使用 WSAEventSelect() 来检测 FD_ACCEPT 网络事件。连接处理程序的(简化)代码是:

SOCKET listener;
HANDLE hStopEvent;

// ... initialise listener and hStopEvent, and other stuff ...

HANDLE hAcceptEvent = WSACreateEvent();
WSAEventSelect(listener, hAcceptEvent, FD_ACCEPT);
HANDLE rghEvents[] = { hStopEvent, hAcceptEvent };

bool bExit = false;
while(!bExit)
{
DWORD nEvent = WaitForMultipleObjects(2, rghEvents, FALSE, INFINITE);
switch(nEvent)
{
case WAIT_OBJECT_0:
bExit = true;
break;
case WAIT_OBJECT_1:
HandleConnect();
WSAResetEvent(hAcceptEvent);
break;
case WAIT_ABANDONED_0:
case WAIT_ABANDONED_0 + 1:
case WAIT_FAILED:
LogError();
break;
}
}

从详细的日志记录我知道,当问题发生时,线程进入 WaitForMultipleObjects() 并且永远不会出现,即使有客户端尝试连接并等待接受。 WAIT_FAILED 和 WAIT_ABANDONED_x 条件永远不会发生。

虽然我没有排除服务器上的配置问题,甚至是某种资源泄漏(找不到任何东西),但我也想知道 WSACreateEvent() 创建的事件是否以某种方式被“解除关联” ' 来自 FD_ACCEPT 网络事件 - 导致它永远不会触发。

所以,我在这里做错了吗?有什么我应该做但我没有做的吗?或者更好的方法?我将不胜感激任何建议!谢谢。

编辑

套接字是非阻塞套接字。

编辑

使用 kipkennedy(下文)建议的方法解决了问题。将 hAcceptEvent 更改为自动重置事件,并删除了对不再需要的 WSAResetEvent() 的调用。

最佳答案

也许 FD_ACCEPT 在 HandleConnect() 期间在 accept() 之后和返回以及随后的 ResetEvent() 之前发出信号。然后,ResetEvent() 最终会重置所有信号,并且不会调用任何重新启用的 accept()。例如,以下顺序是可能的:

  1. 事件发出信号,WaitForMultipleObjects() 返回
  2. 在 HandleConnect() 期间,在调用 accept() 之后的某个时间,事件再次发出信号
  3. HandleConnect() 返回
  4. ResetEvent() 重置事件,屏蔽第二个信号
  5. WaitForMultipleObjects() 永远不会返回,因为就 Windows 而言,它已经发出后续事件的信号并且没有后续的 accepts() 重新启用它

几个可能的解决方案:1) 在 HandleConnect() 中循环 accept() 直到返回 WSAEWOULDBLOCK 2) 使用自动重置事件或在调用 HandleConnect() 之前立即重置事件

关于c++ - Winsock 接受事件有时会停止发出信号 (WSAEventSelect),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2162099/

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