前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于windows完成端口(IOCP)的一些理解(三)

关于windows完成端口(IOCP)的一些理解(三)

作者头像
范蠡
发布2018-04-18 10:17:53
1.5K0
发布2018-04-18 10:17:53
举报

系列目录

关于windows完成端口(IOCP)的一些理解(一)

关于windows完成端口(IOCP)的一些理解(二)

关于windows完成端口(IOCP)的一些理解(三)

关于windows完成端口(IOCP)的一些理解(四)

关于windows完成端口(IOCP)的一些理解(五)

关于windows完成端口(IOCP)的一些理解(六)

1

现在还剩下最后一个问题,就是工作线程如何退出。当然你可以在每次判断标识位前先判断一个退出标识。但是如果工作线程正好被GetQueuedCompletionStatus挂载那里呢?如何唤醒,微软提供了另外一个函数:PostQueuedCompletionStatus,看下这个函数的签名:

代码语言:javascript
复制
BOOL WINAPI PostQueuedCompletionStatus(  
  _In_     HANDLE       CompletionPort,  
  _In_     DWORD        dwNumberOfBytesTransferred,  
  _In_     ULONG_PTR    dwCompletionKey,  
  _In_opt_ LPOVERLAPPED lpOverlapped  
);  

这个函数可以唤醒被GetQueuedCompletionStatus函数挂起的工作线程,当然其第三个参数也是一个CompletionKey(dwCompletionKey)。你可以使用这个dwCompletionKey做标识干一些其它的事情,当然设置一个退出码也可以。例如:

代码语言:javascript
复制
PostQueuedCompletionStatus(m_hIOCompletionPort, 0,
                           (DWORD)EXIT_CODE, NULL);  

这样工作线程里面就可以使用EXIT_CODE来作为退出标志:

代码语言:javascript
复制
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;  
}  

至此,关于完成端口的东西就全部介绍完了。我们小结一下,掌握完成端口的关键在于理解以下几点:

  1. 完成端口绑定了某个socket后,不仅其事件的读写检测由操作系统完成,而且就算是接受新连接、收发数据的动作也是由操作系统代劳了,操作系统完成后会通知你。等你收到通知时,一切都完成好了。你可以直接取出对应的数据使用。
  2. 要想第1点介绍的事情由操作系统代劳,你必须预先准备很多数据结构,比如两端的地址结构体、收发缓冲区、和用来表示新连接的socket等等,这些准备工作可能在程序初始化阶段,也可能在工作线程某个事件处理的地方。
  3. 初始化准备好的各种缓冲区如何在工作线程里面引用到的关键就在于绑定完成端口时CompletionKey和准备收发缓冲区时OVERLAPPED结构体的使用, CompletionKey对应PER Socket Data, OVERLAPPED对应Per IO Data,即CompletionKey是单Socket数据,OVERLAPPED是单IO数据。

由于公众号文章字数有限,您可以接着阅读下一篇:《关于windows完成端口(IOCP)的一些理解(四)》

系列目录

关于windows完成端口(IOCP)的一些理解(一)

关于windows完成端口(IOCP)的一些理解(二)

关于windows完成端口(IOCP)的一些理解(三)

关于windows完成端口(IOCP)的一些理解(四)

关于windows完成端口(IOCP)的一些理解(五)

关于windows完成端口(IOCP)的一些理解(六)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 高性能服务器开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于windows完成端口(IOCP)的一些理解(一)
  • 关于windows完成端口(IOCP)的一些理解(二)
  • 关于windows完成端口(IOCP)的一些理解(三)
  • 关于windows完成端口(IOCP)的一些理解(四)
  • 关于windows完成端口(IOCP)的一些理解(五)
  • 关于windows完成端口(IOCP)的一些理解(六)
  • 关于windows完成端口(IOCP)的一些理解(一)
  • 关于windows完成端口(IOCP)的一些理解(二)
  • 关于windows完成端口(IOCP)的一些理解(三)
  • 关于windows完成端口(IOCP)的一些理解(四)
  • 关于windows完成端口(IOCP)的一些理解(五)
  • 关于windows完成端口(IOCP)的一些理解(六)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档