IOCP网络模型基本步骤

来源:互联网 发布:i5和i7的区别知乎 编辑:程序博客网 时间:2024/05/18 04:54

一、定义结构

   typedef struct PER_HANDLE_DATA 

   {

      SOCKET s;

      SOCKADDR_IN RemoteAddr; 

   }*PPER_HANDLE_DATA;

   typedef struct PER_IO_DATA

   {

     WSAOVERLAPPED ol;

     char buf[12];

     #define OP_READ  1

     #define OP_WRITE 2

     int nOperation;

    }*PPER_IO_DATA;

 

二、创建一个完成端口

   HANDLE hCompletion=CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);

三、创建合适的工作线程

   SYSTEM_INFO si;

   GetSystemInfo(&si);

   for(int i=0;i<si.dwNumberOfProcessors*2;++i)//如果需要使用WaitForSingleObject之类使线程等待,避免CPU空闲

   CreateThread(NULL,0,WorkThread,(LPVOID)hCompletion,0,0);

四、绑定监听socket

   SOCKET sListen=socket(AF_INET,SOCK_STREAM,0);

   SOCKADDR_IN srvaddr;

   srvaddr.sin_addr.S_un.S_addr=INADDR_ANY;

   srvaddr.sin_family=AF_INET;

   srvaddr.sin_port=htons(4567);

   bind(s,(SOCKADRR*)&srvaddr,sizeof srvaddr);

   listen(s,5);

五、处理客户连接

   while(1)

   {

      SOCKADDR_IN Remoteaddr;

      int nlen=sizeof Remoteaddr;

      SOCKET sAccept=accept(sListen,(SOCKADDR*)Remoteaddr,&nlen);

      PPER_HANDLE_DATA pPerHandle=(PER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));

      pPerHandle->s=sAccept;

      memcpy(&pPerHandle->RemoteAddr,Remoteaddr,nlen);

 

      CreateIoCompletionPort((HANDLE)pPerHandle->s,hCompletion,(DWORD)perHandle,0);//关联per数据

      PPER_IO_DATA pPerIO=(PER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));

      pPerIO->nOperation=OP_READ;

      WSABUF buf;

      buf.buf=pPerIO->buf;

      buf.len=12;

      DWORD dwRecv;

      DWORD dwFlags=0;

      WSARecv(pPerHandle->s,&buf,1,&dwRecv,&dwFlags,&pPerIO->ol,NULL);//投递第一个请求

   }

六、处理客户请求(工作线程)

   HANDLE hCompletion=(HANDLE)lpParam;

   DWORD dwTrans;

   PPER_HANDLE_DATA pPerHandle;

   PPER_IO_DATA pPerIO;

 

   while(1)

   {

     bool ok=GetQueuedCompletionStatus(hCompletion,&dwTrans,(PULONG_PTR)&pPerHandle,(LPOVERLAPPED*)&pPerIO,WSA_INFINITE);//查看是否有异步IO请求完成 完成返回

     if(!bok)//出错了

     {

       closesocket(pPerHandle->s);

       GlobalFree(pPerHandle);

       GlobalFree(pPerIO);

       continue;

     }

     if(dwTrans==0&&(pPerIO->nOperation==OP_READ||pPerIO->nOperation==OP_WRITE))//连接关闭了

     {

      closesocket(pPerHandle->s);

      GlobalFree(pPerHandle);

      GlobalFree(pPerIO);

      continue; 

     }

     switch(pPerIO->nOperation)

     {

       case OP_READ:

         pPerIO->buf[dwTrans]='/0';

         printf(pPerIO->buf);

         WSABUF buf;

         buf.buf=pPerIO->buf;

         buf.len=12;

         pPerIO->nOperation=OP_READ;

         DWORD nFlags=0;

         WSARecv(pPerHandle->s,&buf,1,&dwTrans,&nFlags,&pPerIO->ol,NULL);//继续投递

         break;

      case OP_WRITE:

      case OP_ACCEPT:

         break;

     }

 

   }

原创粉丝点击