我有一个用C++编写的Windows服务,它充当监听传入连接的TCP服务器。
我初始化了服务器套接字,并将accept代码放在一个单独的线程中。这将接受并处理传入的连接。
但是,如果服务接收到停止信号,我也需要停止这个线程。因此,我想使用CreateEvent创建一个事件对象,并等待发出信号。此等待将发生在创建接受线程的线程中。因此,当收到停止信号时,我可以使用TerminateThread函数来停止接受线程。
然而,MSDN说
TerminateThread是一个危险的函数,只能在最极端的情况下使用。
我的做法是正确的吗?还有什么办法可以做到这一点呢?
发布于 2014-09-24 06:44:48
在Windows中,只需调用accept即可从另一个线程唤醒阻塞的closesocket调用。阻塞的accept调用将返回-1,并且您的代码有机会通过检查已经设置的其他退出条件(例如全局变量)来突破它所处的任何循环。
这也适用于close函数的Mac (可能还有BSD衍生物),但不适用于Linux。解决此问题的更通用的UNIX解决方案是这里。
下面的Windows解决方案的一些pseduo代码。
SOCKET _listenSocket;
bool _needToExit = false;
HANDLE _hThread;
void MakeListenThreadExit()
{
_needToExit = true;
closesocket(_listenSocket);
_listenSocket = INVALID_SOCKET;
// wait for the thread to exit
WaitForSingleObject(_hThread, INFINITE);
}
DWORD __stdcall ListenThread(void* context)
{
while (_needToExit == false)
{
SOCKET client = accept(_listenSocket, (sockaddr*)&addr, &addrSize);
if ((client == -1) || _needToExit)
{
break;
}
ProcessClient(client);
}
return 0;
}发布于 2014-09-24 08:36:21
在这种情况下,不要在阻塞套接字上使用accept()。使用非阻塞套接字代替。然后,您可以在超时时使用select(),这样线程就可以定期检查终止条件。或者更好的方法是,将WSACreateEvent()与WSASelectEvent()一起使用。创建两个事件对象,一个用于检测客户端连接,另一个用于检测线程终止。然后可以使用WSAWaitForMultipleEvents()同时等待两个事件。使用WSASetEvent()在需要时向终止事件发出信号,并在其他事件发出信号时调用accept()或WSAAccept()。WSAWaitForMultipleEvents()会告诉你该对哪个事件采取行动。
https://stackoverflow.com/questions/26010024
复制相似问题