织梦CMS - 轻松建站从此开始!

罗索

闲侃完成端口

jackyhwei 发布于 2011-07-22 09:18 点击:次 
ACE是个好东东,可是真正用的时候,我还是忍不住重新造车轮。做网络层的时候,考虑了一下还是自己做吧(并不是我觉得ACE不好或不方便,只是因为自己ACE不精,怕乱舞伤了自己)。
TAG:

ACE是个好东东,可是真正用的时候,我还是忍不住重新造车轮。做网络层的时候,考虑了一下还是自己做吧(并不是我觉得ACE不好或不方便,只是因为自己ACE不精,怕乱舞伤了自己)。

从好多方面来说,我都是c++的铁杆,自己给自己的评价是对c++有较深入的认识。不过因为闲时太喜欢做coding游戏,为了节省时间快速见 效,投奔锐利c(c#,嘿嘿)了。扯远了,当用c#造车轮的时候,我想到了尽可能使用原生api的c++完成端口可能会对我有帮助,于是简单写了几行。

  1. class thethe 
  2. public
  3.     bool    Init(); 
  4.  
  5. private
  6.     HANDLE  m_hiocp;    //完成端口句柄 
  7.     HANDLE  m_hworker;  //工作者线程 
  8.     static  DWORD   WINAPI  toworker(LPVOID lpthis); 
  9.     SOCKET  m_listener;     //服务器监听socket 
  10. }; 
  11.  
  12. bool thethe::Init() 
  13.     //创建服务器监听socket,必不可少的。 
  14.     sockaddr_in listeneraddr; 
  15.     listeneraddr.sin_addr.s_addr = INADDR_ANY; 
  16.     listeneraddr.sin_family = AF_INET; 
  17.     listeneraddr.sin_port   = htons(2350); 
  18.     m_listener  = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
  19.     bind(m_listener,(sockaddr*)&listeneraddr,sizeof(sockaddr_in)); 
  20.     listen(m_listener,5); 
  21.  
  22.     //1.创建完成端口句柄 
  23.     m_hiocp = CreateIoCompletionPort(NULL,NULL,NULL,0);  
  24.  
  25.     //2.创建工作者线程 
  26.     m_hworker   = CreateThread(NULL,NULL,toworker,(LPVOID)this,0,NULL);      
  27.  
  28. while(true
  29.     {    
  30.         SOCKET  client; 
  31.         //4.主线程循环使用accept处理新的连接 
  32. client  = accept(m_listener,(sockaddr*)&listeneraddr,sizeof(listeneraddr));  
  33.         //6.主线程阻塞等待下一次连接     
  34.         perIoInfo* pif  = new perIoInfo; 
  35.         pif->sock   = client; 
  36.         //5.直接把新的连接关联到完成端口上,然后投放接受请求,直接返回 
  37. CreateIoCompletionPort(client,m_hiocp,pif,0);                
  38.         myoverlapped* pov = new myoverlapped; 
  39.         pov->wbuf.buf   = pov->buf; 
  40.         pov->wbuf.len   = BUF_SIZE; 
  41.  
  42.         DWORD   flag; 
  43.  
  44.         //投放请求 
  45.         WSARecv(client,pov->buf,&pov->wbuf.buf,1,&flag,pov,NULL);            
  46.         //7.操作系统在操作完成后通知完成端口 
  47.     } 
  48.  
  49. DWORD   WINAPI thethe::toworker( LPVOID lpthis ) 
  50.     thethe* pthis   = static_cast<thethe*>(lpthis); 
  51.     bool    bgqcsRet;//GetQueuedCompletionStatus结果 
  52.     DWORD   nofbytes;//做为GetQueuedCompletionStatus的lpNumberOfBytesTransferred参数使用 
  53.     perIoInfo   comKey;//用以满足GQCS函数的第三个参数 
  54.     LPOVERLAPPED    stoverlapped;//满足GQCS第四个参数 
  55.     while (true
  56.     { 
  57.         //3.工作者线程使用阻塞模式等待完成端口信号 
  58.         bgqcsRet    = GetQueuedCompletionStatus(pthis->m_hiocp,&nofbytes
  59. ,&comKey,&stoverlapped,INFINITE);    
  60.  
  61.         //8.取回刚才投放的消息 
  62.         //9.处理完毕后投放新的处理请求(一般是投放新的读请求) 
  63.     } 
  64.  
  65.     return  0; 

为了把事情最简单化,我让完成端口只处理接收问题,实际使用中,listener也可以绑定在完成端口上,在完成工作者线程中处理接受新的连接工作。

值得说明的是,GetQueuedCompletionStatus的第三个参数lpCompletionKey和 CreateIoCompletionPort的第三个参数CompletionKey是同一类型,其实是在 CreateIoCompletionPort中我们传入,操作系统在暂时代我们保管,在GetQueuedCompletionStatus函数中把这 个参数返回。也就是说,这个参数是和句柄关联的(这里的句柄也就是socket了)。

既然说到CompletionKey了,那就再说说GetQueuedCompletionStatus的lpOverlapped参数。对于 句柄sock而已,它可以产生的信号有:accept、recv、send(close是一种特殊的recv)几种,对应的函数AcceptEx、 WSARecv、WSASend都有lpOverlapped参数,秘诀就在这里,GetQueuedCompletionStatus取出了我们关心的 所有信息(我们无非关心句柄、数据两部分的信息)。

(win2ks)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201107/14741.html]
本文出处:blog.csdn.net/win2ks 作者:win2ks
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容