ACE是个好东东,可是真正用的时候,我还是忍不住重新造车轮。做网络层的时候,考虑了一下还是自己做吧(并不是我觉得ACE不好或不方便,只是因为自己ACE不精,怕乱舞伤了自己)。
从好多方面来说,我都是c++的铁杆,自己给自己的评价是对c++有较深入的认识。不过因为闲时太喜欢做coding游戏,为了节省时间快速见 效,投奔锐利c(c#,嘿嘿)了。扯远了,当用c#造车轮的时候,我想到了尽可能使用原生api的c++完成端口可能会对我有帮助,于是简单写了几行。
- class thethe
- {
- public:
- bool Init();
-
- private:
- HANDLE m_hiocp;
- HANDLE m_hworker;
- static DWORD WINAPI toworker(LPVOID lpthis);
- SOCKET m_listener;
- };
-
- bool thethe::Init()
- {
-
- sockaddr_in listeneraddr;
- listeneraddr.sin_addr.s_addr = INADDR_ANY;
- listeneraddr.sin_family = AF_INET;
- listeneraddr.sin_port = htons(2350);
- m_listener = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- bind(m_listener,(sockaddr*)&listeneraddr,sizeof(sockaddr_in));
- listen(m_listener,5);
-
-
- m_hiocp = CreateIoCompletionPort(NULL,NULL,NULL,0);
-
-
- m_hworker = CreateThread(NULL,NULL,toworker,(LPVOID)this,0,NULL);
-
- while(true)
- {
- SOCKET client;
-
- client = accept(m_listener,(sockaddr*)&listeneraddr,sizeof(listeneraddr));
-
- perIoInfo* pif = new perIoInfo;
- pif->sock = client;
-
- CreateIoCompletionPort(client,m_hiocp,pif,0);
- myoverlapped* pov = new myoverlapped;
- pov->wbuf.buf = pov->buf;
- pov->wbuf.len = BUF_SIZE;
-
- DWORD flag;
-
-
- WSARecv(client,pov->buf,&pov->wbuf.buf,1,&flag,pov,NULL);
-
- }
- }
-
- DWORD WINAPI thethe::toworker( LPVOID lpthis )
- {
- thethe* pthis = static_cast<thethe*>(lpthis);
- bool bgqcsRet;
- DWORD nofbytes;
- perIoInfo comKey;
- LPOVERLAPPED stoverlapped;
- while (true)
- {
-
- bgqcsRet = GetQueuedCompletionStatus(pthis->m_hiocp,&nofbytes
- ,&comKey,&stoverlapped,INFINITE);
-
-
-
- }
-
- 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) |