【发布时间】:2010-01-29 13:11:43
【问题描述】:
我对属于多线程套接字服务器的一段遗留 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() 的调用。
【问题讨论】:
标签: c++ windows events winsock