现在的位置: 首页 > 综合 > 正文

关于完成端口的应用,问一下,完成端口是不是只能用来做服务器?

2013年08月01日 ⁄ 综合 ⁄ 共 6727字 ⁄ 字号 评论关闭

DWORD   WINAPI   ServerWorkerThread(LPVOID   lpParam)  
  {  
          HANDLE   CompletionPort   =   (HANDLE)lpParam;  
          DWORD   BytesTransferred;  
          LPOVERLAPPED   lpOverlapped;  
          LPPER_HANDLE_DATA   PerHandleData   =   NULL;  
          LPPER_IO_DATA   PerIoData   =   NULL;  
          DWORD   SendBytes;  
          DWORD   RecvBytes;  
          DWORD   Flags;  
          BOOL   bRet   =   FALSE;  
   
          while   (TRUE)  
          {  
                  bRet   =   GetQueuedCompletionStatus(CompletionPort,  
                                                                                    &BytesTransferred,  
                                                                                    (PULONG_PTR)      
                                                                                        &PerHandleData,  
                                                                                    (LPOVERLAPPED*)  
                                                                                        &lpOverlapped,  
                                                                                    INFINITE);  
   
                  //   检查成功的返回,这儿要注意使用这个宏CONTAINING_RECORD  
                  PerIoData   =   (LPPER_IO_DATA)CONTAINING_RECORD(lpOverlapped,    
                                                                                                            PER_IO_DATA,    
                                                                                                            Overlapped);  
   
                  //   先检查一下,看看是否在套接字上已有错误发生  
                  if   (0   ==   BytesTransferred)    
                  {  
                          closesocket(PerHandleData->Socket);  
                          GlobalFree(PerHandleData);  
                          GlobalFree(PerIoData);  
   
                          continue;  
                  }  
   
                  //   数据处理  
                  //   成功了!!!这儿就收到了来自客户端的数据  
              //     cout   <<   PerIoData->DataBuf.buf   <<   endl;  
  // MessageBox("sffdasf");  
  AfxMessageBox(PerIoData->DataBuf.buf);  
   
                  Flags   =   0;  
   
                  //   为下一个重叠调用建立单I/O操作数据  
                  ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));  
   
                  PerIoData->DataBuf.len   =   1024;  
                  PerIoData->DataBuf.buf   =   PerIoData->buffer;  
                  PerIoData->OperationType   =   0;   //   read  
                  WSARecv(PerHandleData->Socket,  
                                  &(PerIoData->DataBuf),  
                                  1,  
                                  &RecvBytes,  
                                  &Flags,  
                                  &(PerIoData->Overlapped),  
                                  NULL);  
          }  
   
          return   0;  
  }  
  int   StartWinsock(void)    
  {    
      WSADATA   wsa;    
      return   WSAStartup(MAKEWORD(2,2),&wsa);   //2,0  
  }    
  void   Ccptest_netDlg::OnBnClickedButton1()  
  {  
  //   TODO:   在此添加控件通知处理程序代码  
  SYSTEM_INFO   SystemInfo;  
  CString   ctemp;  
   
  struct   sockaddr_in   InternetAddr;   /*   目标地址   */  
  SOCKET   Listen;  
  int   i;  
  WSADATA   wsd;  
   
  HANDLE   CompletionPort;  
  //   Load   Winsock  
   
  StartWinsock();//MAKEWORD(2,2),   &wsd);  
   
  //   Step   1:  
  //   Create   an   I/O   completion   port  
   
  CompletionPort   =   CreateIoCompletionPort(  
          INVALID_HANDLE_VALUE,   NULL,   0,   0);  
   
  //   Step   2:  
  //   Determine   how   many   processors   are   on   the   system  
   
  GetSystemInfo(&SystemInfo);  
   
  //   Step   3:  
  //   Create   worker   threads   based   on   the   number   of  
  //   processors   available   on   the   system.   For   this  
  //   simple   case,   we   create   one   worker   thread   for   each  
  //   processor.  
   
  for(i   =   0;   i   <   SystemInfo.dwNumberOfProcessors;   i++)  
  {  
          HANDLE   ThreadHandle;  
   
          //   Create   a   server   worker   thread,   and   pass   the  
          //   completion   port   to   the   thread.   NOTE:   the  
          //   ServerWorkerThread   procedure   is   not   defined  
          //   in   this   listing.  
   
          ThreadHandle   =   CreateThread(NULL,   0,  
                  ServerWorkerThread,   CompletionPort,  
                  0,   NULL);  
   
          //   Close   the   thread   handle  
          CloseHandle(ThreadHandle);  
  }  
   
  //   Step   4:  
  //   Create   a   listening   socket  
   
  Listen   =   WSASocket(AF_INET,   SOCK_STREAM,   0,   NULL,   0,  
          WSA_FLAG_OVERLAPPED);  
   
  InternetAddr.sin_family   =   AF_INET;  
  InternetAddr.sin_addr.s_addr   =   htonl(INADDR_ANY);  
  InternetAddr.sin_port   =   htons(5150);  
  bind(Listen,   (PSOCKADDR)   &InternetAddr,  
          sizeof(InternetAddr));  
   
  //   Prepare   socket   for   listening  
   
  listen(Listen,   5);  
   
  while(TRUE)  
  {  
          PER_HANDLE_DATA   *PerHandleData=NULL;  
          SOCKADDR_IN   saRemote;  
          SOCKET   Accept;  
          int   RemoteLen;  
          //   Step   5:  
          //   Accept   connections   and   assign   to   the   completion  
          //   port  
   
          RemoteLen   =   sizeof(saRemote);  
          Accept   =   WSAAccept(Listen,   (SOCKADDR   *)&saRemote,   &RemoteLen,NULL,   0);  
   
          //   Step   6:  
          //   Create   per-handle   data   information   structure   to    
          //   associate   with   the   socket  
          PerHandleData   =   (LPPER_HANDLE_DATA)    
                  GlobalAlloc(GPTR,   sizeof(PER_HANDLE_DATA));  
   
          printf("Socket   number   %d   connected/n",   Accept);  
          PerHandleData->Socket   =   Accept;  
          memcpy(&PerHandleData->ClientAddr,   &saRemote,   RemoteLen);  
   
          //   Step   7:  
          //   Associate   the   accepted   socket   with   the  
          //   completion   port  
   
          CreateIoCompletionPort((HANDLE)   Accept,  
                  CompletionPort,   (DWORD)   PerHandleData,   0);  
   
          //   Step   8:  
          //     Start   processing   I/O   on   the   accepted   socket.  
          //     Post   one   or   more   WSASend()   or   WSARecv()   calls  
          //     on   the   socket   using   overlapped   I/O.  
  WSASend(Listen,  
       
  }  
   
   
  }  
  Top

2 楼clicksoft(好啊)回复于 2005-05-06 18:19:00 得分 0

可以   但有必要吗Top

3 楼tccsdn(紫乐)回复于 2005-05-06 18:20:55 得分 0

upTop

4 楼laiyiling(Graphics ◎ Multimedia)回复于 2005-05-06 19:29:29 得分 0

网上有很多完成断口的例子  
  http://www.vckbase.com/document/viewdoc/?id=980Top

5 楼anycom()回复于 2005-05-06 23:00:41 得分 0

为什么说没必要??????Top

6 楼jasic2002()回复于 2005-05-07 08:08:44 得分 0

只是一书之言,微软建议服务端用完成端口,客户端使用基于消息的socket通讯!Top

7 楼krh2001(边城浪子)回复于 2005-05-07 08:11:06 得分 0

对于需要连接大量客户端的服务器来说,   完成端口是不错的选择。  
   
  对于客户端来说,没有必要。Top

8 楼stonex_2000(三棱镜)回复于 2005-05-07 11:07:29 得分 0

可以的,但完成端口不能在win98上使用.客户端都是win2k以上吗?Top

9 楼wy99sinacom(道)回复于 2005-05-11 14:49:43 得分 0

没有必要Top

10 楼llm06(blacksheep)回复于 2005-05-11 15:11:51 得分 0

应该是可以的。  
  只需要把你的套接字与完成端口关联起来,然后投递异步的请求,在线程池里面处理完成的i/o请求就可以了。  
  www.codeproject.com里面有一个完成端口的例子,写的还可以,不过有很多bug,下载了学习一下。Top

11 楼dingpiao(.......)回复于 2005-05-13 22:49:07 得分 0

客户端要处理很多连接吗?  
  那你不成了服务器了呀?Top

12 楼shicheng521()回复于 2005-05-14 15:36:53 得分 0

一个客户机就那么多的连接,   那服务器器不是受不了了吗?  
  是不是想把它给弄死呀Top

13 楼Practise_Think(时代“过客”)回复于 2005-05-14 22:13:17 得分 0

完全可以的,你试试吧!!!Top

14 楼anycom()回复于 2005-05-26 16:07:41 得分 0

偶就是想同时边上万儿八千的服务器,采网页。。。。。。。。。。  
   
  但好像关于完成端口主动连接的例程特别少!!!Top

15 楼anycom()回复于 2005-05-26 16:18:42 得分 0

偶就是想同时连上万儿八千的服务器,采网页。。。。。。。。。。  
   
  但好像关于完成端口主动连接的例程特别少!!!  
  Top

16 楼anycom()回复于 2005-05-26 16:19:14 得分 0

望高人们给点例程Top

17 楼flashboy(爱写程序的小绵羊)回复于 2005-05-28 23:25:03 得分 0

完成端口主动连接的一个典型例子就是"代理服务器". 你可以找一下完成端口模型的代理服务器的代码,里面既有响应连接,也有主动连接. 但是如果只是做一个纯CLIENT,建议没有必要用IOCP这么复杂,完全可以用重叠IO模型或者SELECT模型.IOCP的优势是体现在大量并发连接的响应与管理上,所以来做服务器更加可以体现其优势出来.Top

18 楼SmallBigCat(乱花渐欲迷人眼)回复于 2005-05-30 17:05:58 得分 0

服務器的級聯還是用得上的  
   
  1:先建立個連接  
  2:Connect到對方得服務器  
  3:將socket句柄綁定在iocp句柄上  
  4:投遞一個WSARecv操作Top

19 楼tgame(从此醉)回复于 2005-05-31 18:06:24 得分 0

SmallBigCat(。。。)   说的对,的确是那样的Top

20 楼anycom()回复于 2005-06-10 20:23:51 得分 0

偶就是要同时连上万儿八千个服务器。Top

21 楼lianglp(寻找黄金分割点)回复于 2005-06-10 22:12:26 得分 0

没关系,无论是服务器还是客户端,用TCP或UDP都可以,  
  其实IOCP只是一种实现IO输入输出模型,对它来说,根本不知道  
  是socket句柄或其它句柄,实际上这个模型是一个被动模型,  
  IO句柄是否可以关联到IOCP,其实是看这个IO句柄是否支持它有关。  
  Top

22 楼Hellboy(int argc, char* argv[])回复于 2005-06-13 17:15:27 得分 0

connect成功以后,  
   
    CreateIoCompletionPort((HANDLE)   client,  
  CompletionPort,   (DWORD)   PerHandleData,   0);  
  将连接成功的socket加到完成端口,以后对于这个socket调用的WSASend,WSARecv都会在这个完成端口上得到通知.  
  具体的代码自己写一下吧.  
   
  我们公司模拟大量客户端测试的代码就用了用于连接的完成端口.  
  效果还不错.   
 

抱歉!评论已关闭.