系列目录
1
现在还剩下最后一个问题,就是工作线程如何退出。当然你可以在每次判断标识位前先判断一个退出标识。但是如果工作线程正好被GetQueuedCompletionStatus挂载那里呢?如何唤醒,微软提供了另外一个函数:PostQueuedCompletionStatus,看下这个函数的签名:
BOOL WINAPI PostQueuedCompletionStatus(
_In_ HANDLE CompletionPort,
_In_ DWORD dwNumberOfBytesTransferred,
_In_ ULONG_PTR dwCompletionKey,
_In_opt_ LPOVERLAPPED lpOverlapped
);
这个函数可以唤醒被GetQueuedCompletionStatus函数挂起的工作线程,当然其第三个参数也是一个CompletionKey(dwCompletionKey)。你可以使用这个dwCompletionKey做标识干一些其它的事情,当然设置一个退出码也可以。例如:
PostQueuedCompletionStatus(m_hIOCompletionPort, 0,
(DWORD)EXIT_CODE, NULL);
这样工作线程里面就可以使用EXIT_CODE来作为退出标志:
DWORD ThreadFunction()
{
OVERLAPPED *pOverlapped = NULL;
PER_SOCKET_CONTEXT *pSocketContext = NULL;
DWORD dwBytesTransfered = 0;
BOOL bReturn = GetQueuedCompletionStatus(m_hIOCompletionPort,
&dwBytesTransfered,
(PULONG_PTR)&pSocketContext,
&pOverlapped, INFINITE);
// 如果收到的是退出标志,则直接退出
if ( EXIT_CODE==(DWORD)pSocketContext )
{
return 0;
}
if (((SOME_STRUCT*)pSocketContext)->s == 侦听socket句柄)
{
/*连接成功后可以做以下事情:
1. 获取对端和本端的ip地址和端口号,
即AcceptEx的第三个参数lpOutputBuffer中拿
(这一步,不是必须)
2. 如果对端连接成功后会发数据过来,
则可以从初始化时调用AcceptEx准备的缓冲区里面拿到
即AcceptEx的第三个参数lpOutputBuffer中拿
(这一步不是必须)
3. 再次调用AcceptEx补充一个sAcceptSocket
(这一步是必须的)
4. 调用WSASend准备发送数据工作
或调用WSARecv准备接收数据工作(这一步,不是必须)*/
}
//普通客户端socket收发数据
else
{
//通过pOverlapped结构得到pIOContext
PER_IO_CONTEXT* pIOContext = (PER_IO_CONTEXT*)pOverlapped;
if (pIOContext->Type == 收)
{
//解析收到的数据(这一步,不是必须)
//调用WSASend准备发送数据工作(比如应答客户端)(这一步,不是必须)
//继续调用WSARecv准备收取数据工作(这一步,不是必须)
}
else if (pIOContext->Type == 发)
{
//调用WSARecv准备收取数据工作(这一步,不是必须)
}
}
return 0;
}
至此,关于完成端口的东西就全部介绍完了。我们小结一下,掌握完成端口的关键在于理解以下几点:
由于公众号文章字数有限,您可以接着阅读下一篇:《关于windows完成端口(IOCP)的一些理解(四)》
系列目录
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有