zoukankan      html  css  js  c++  java
  • IOCP Normal process code

    step:

    1.初始化Winsock
    2.创建一个完成端口
    3.根据服务器线程数创建一定量的线程数
    4.准备好一个socket进行bind然后listen
    5.进入循环accept等待客户请求
    6.创建一个数据结构容纳socket和其他相关信息
    7.将连进来的socket同完成端口相关联
    8.投递一个准备接受的请求
    以后就不断的重复5至8的过程

    1: include

    #define WIN32_LEAN_AND_MEAN      //定义宏,不会出现error C2011: 'fd_set' : 'struct' type redefinition等错误
    #define VC_EXTRALEAN
     
    #include <windows.h>
    #include <winsock2.h>
    #include "iostream"
    #pragma comment(lib, "Ws2_32.lib")

    2: define data structure

    typedef struct         
    {
     OVERLAPPED Overlapped;
     WSABUF DataBuf;
     CHAR Buffer[DATA_BUFSIZE];                    
     DWORD BytesSEND;                                 //发送字节数
     DWORD BytesRECV;                                
    } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
     
     
    typedef struct
    {
     SOCKET Socket;
    } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;

    3: init socket

       1:  WORD wVersionRequested;
       2:  WSADATA wsaData;
       3:  int Ret;
       4:   
       5:  wVersionRequested = MAKEWORD(2,0);
       6:  //err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
       7:   if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
       8:   {
       9:        printf("WSAStartup failed with error %d\n", Ret);
      10:        return;
      11:   } 

    4: allocate gloal heap memory

       1:  //使用NEW不可以 PerHandleData = new PER_HANDLE_DATA;
       2:   if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
       3:   {
       4:     printf("GlobalAlloc() failed with error %d\n", GetLastError());
       5:     return;
       6:   }      

    5: server side

       1:   
       2:  //server.cpp
       3:  #include <winsock2.h>
       4:  #include <windows.h>
       5:  #include "socketapi.h"
       6:  #include "socketnotify.h"
       7:  #include "iostream"
       8:   
       9:  using namespace std;
      10:  #pragma comment(lib, "Ws2_32")
      11:   
      12:  #define OP_READ     0
      13:  #define OP_WRITE    1
      14:  #define OP_ACCEPT   2
      15:  #define DATA_BUFSIZE 1024
      16:   
      17:   
      18:   
      19:  typedef struct
      20:  {
      21:      OVERLAPPED Overlapped;
      22:      WSABUF DataBuf;
      23:      CHAR Buffer[DATA_BUFSIZE];                     
      24:      DWORD BytesSEND;                                 //发送字节数
      25:      DWORD BytesRECV;                                 
      26:  } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
      27:   
      28:   
      29:  typedef struct
      30:  {
      31:      SOCKET Socket;
      32:  } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
      33:   
      34:   
      35:  DWORD __stdcall CompletionRoutine(LPVOID Param);
      36:  int main()
      37:  {
      38:      WORD wVersionRequested;
      39:      WSADATA wsaData;
      40:      int Ret;
      41:      
      42:      wVersionRequested = MAKEWORD(2,0);
      43:      //err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
      44:      if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
      45:     {
      46:        printf("WSAStartup failed with error %d\n", Ret);
      47:        return;
      48:     } 
      49:      HANDLE    CompletionPort;
      50:      LPPER_HANDLE_DATA PerHandleData ;
      51:      LPPER_IO_OPERATION_DATA     PerIoData ;
      52:      SOCKADDR_IN InternetAddr;
      53:      DWORD RecvBytes;
      54:      DWORD Flags;
      55:      SOCKET server;
      56:      SOCKET Accept;
      57:      if ((server = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
      58:          WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
      59:      {
      60:          printf("WSASocket() failed with error %d\n", WSAGetLastError());
      61:          return;
      62:      }
      63:      InternetAddr.sin_family = AF_INET;
      64:      InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
      65:      InternetAddr.sin_port = htons(8000);
      66:      if (bind(server, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
      67:      {
      68:          printf("bind() failed with error %d\n", WSAGetLastError());
      69:          WSACleanup();
      70:          return;
      71:      }   
      72:      
      73:      if (listen(server, 5) == SOCKET_ERROR)
      74:      {
      75:          printf("listen() failed with error %d\n", WSAGetLastError());
      76:          WSACleanup();
      77:          return;
      78:      }
      79:      //    server.set_port(8000);
      80:      //    server.listen();
      81:      ///////////////////////////
      82:      //取得系统中CPU的数目,创建和CPU数目相等的线程,如果事先估计到完成端口处理线程会堵塞,
      83:      //可以考虑创建 SysInfo.dwNumberOfProcessors*2个线程。一般在单处理器上创建和CPU数目相等
      84:      //的线程就可以了
      85:      //获得CPU个数
      86:      SYSTEM_INFO sysInfo;    
      87:      ZeroMemory(&sysInfo,sizeof(SYSTEM_INFO));
      88:      ZeroMemory(&wsaData,sizeof(WSADATA));    
      89:      GetSystemInfo(&sysInfo);    
      90:      int nNumberOfConcurrent = sysInfo.dwNumberOfProcessors * 2+2;    
      91:      
      92:      CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nNumberOfConcurrent);
      93:      if (NULL == CompletionPort)
      94:      {
      95:          cout << "CreateIoCompletionPort() failed: " << GetLastError() << endl;
      96:          
      97:          return ;
      98:      }
      99:      
     100:      PER_IO_OPERATION_DATA per_io_data;
     101:      
     102:      cout<<"port:"<<CompletionPort<<endl;
     103:      HANDLE     m_hThreadArray[8];
     104:      for (int i=0; i<1; i++)
     105:      {
     106:          m_hThreadArray[i] = CreateThread(NULL, 0, CompletionRoutine, (LPVOID)CompletionPort, 0, NULL);
     107:          if (NULL == m_hThreadArray[i])
     108:          {
     109:              while (i>0)
     110:              {
     111:                  CloseHandle(m_hThreadArray[i-1]);
     112:                  m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
     113:                  i--;
     114:              }//end of while
     115:              
     116:              cout << "CreateThread() failed: " << GetLastError() << endl;
     117:              CloseHandle(CompletionPort);
     118:              
     119:              
     120:              return  ;
     121:          }
     122:      }//end of for
     123:      
     124:      Sleep(1000);
     125:      while(1)
     126:      {
     127:          cout<<"waiting for accept "<<endl;
     128:          //int sClient = server.accept();
     129:          
     130:          if ((Accept = WSAAccept(server, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
     131:          {
     132:              printf("WSAAccept() failed with error %d\n", WSAGetLastError());
     133:              return;
     134:          }
     135:          
     136:          cout<<"accetp :"<<Accept<<endl;
     137:          
     138:          //PerHandleData = new PER_HANDLE_DATA;
     139:          if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
     140:          {
     141:              printf("GlobalAlloc() failed with error %d\n", GetLastError());
     142:              return;
     143:          }      
     144:          PerHandleData->Socket = Accept;
     145:          if(CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD)PerHandleData, 0) == NULL)
     146:          {
     147:              printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
     148:              return ;
     149:              
     150:          }
     151:          //PerIoData  = new PER_IO_OPERATION_DATA;
     152:          //
     153:          //清管子的数据结构,准备往里面灌数据
     154:          //
     155:          if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
     156:          {
     157:              printf("GlobalAlloc() failed with error %d\n", GetLastError());
     158:              return;
     159:          }
     160:          memset(&(PerIoData->Overlapped), sizeof(OVERLAPPED),0);
     161:          PerIoData->BytesSEND = 0;
     162:          PerIoData->BytesRECV = 0;
     163:          PerIoData->DataBuf.len = DATA_BUFSIZE;
     164:          PerIoData->DataBuf.buf = PerIoData->Buffer;
     165:          
     166:          //
     167:          //  accept接到了数据,就放到PerIoData中,而perIoData又通过线程中的函数取出,
     168:          //
     169:          
     170:          RecvBytes = 0;
     171:          Flags = 0;
     172:          if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
     173:              &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
     174:          {
     175:              if (WSAGetLastError() != ERROR_IO_PENDING)
     176:              {
     177:                  printf("main WSARecv() failed with error %d\n", WSAGetLastError());
     178:                  WSACleanup();
     179:                  return;
     180:              }
     181:          }
     182:          //cout<<"recv :"<<PerIoData->Buffer<<endl;
     183:          
     184:          
     185:          
     186:      }
     187:      PostQueuedCompletionStatus(CompletionPort, 0xFFFFFFFF, 0, NULL);
     188:      CloseHandle(CompletionPort);
     189:      
     190:      WSACleanup();
     191:   
     192:      cin>>i;
     193:      return ;
     194:  }
     195:   
     196:  DWORD __stdcall CompletionRoutine(LPVOID Param)
     197:  {
     198:      
     199:      HANDLE CompletionPort = (HANDLE) Param;
     200:      
     201:      PER_IO_OPERATION_DATA *pData = (PER_IO_OPERATION_DATA*)Param;
     202:      
     203:      DWORD BytesTransferred;
     204:      LPOVERLAPPED Overlapped;
     205:      LPPER_HANDLE_DATA PerHandleData;
     206:      LPPER_IO_OPERATION_DATA PerIoData;         
     207:      DWORD SendBytes, RecvBytes;
     208:      DWORD Flags;
     209:      
     210:      
     211:      
     212:      while(1)
     213:      {
     214:   
     215:          int bSuccess = GetQueuedCompletionStatus(
     216:              CompletionPort,
     217:              &BytesTransferred,
     218:              (LPDWORD)&PerHandleData,
     219:              (LPOVERLAPPED *) &PerIoData,
     220:              INFINITE
     221:              );
     222:          
     223:          cout<<"----------------------------"<<endl;
     224:          
     225:          if (0 == bSuccess)
     226:          {
     227:              if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
     228:              &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
     229:              {
     230:                  int iError = WSAGetLastError();
     231:                  if ( iError!= ERROR_IO_PENDING)
     232:                  {
     233:                      printf("client %d closed \n", PerHandleData->Socket);
     234:                      closesocket(PerHandleData->Socket);
     235:                  }
     236:              }
     237:              
     238:              continue;
     239:          }
     240:          if (NULL == PerIoData)
     241:          {
     242:              //
     243:              cout<<"//PostQueuedCompletionStatus发过来一个空的单句柄数据,表示线程要退出了。"<<endl;
     244:              //
     245:              return 0;
     246:          }
     247:          Flags = 0;
     248:          if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
     249:              &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
     250:          {
     251:              if (WSAGetLastError() != ERROR_IO_PENDING)
     252:              {
     253:                  printf("thread WSARecv() failed with error %d\n", WSAGetLastError());
     254:                  return 0;
     255:              }
     256:          }
     257:          
     258:          cout<<"recv from "<<PerHandleData->Socket<<":"<<PerIoData->Buffer<<endl;
     259:          
     260:          
     261:      }
     262:      
     263:      return 0;
     264:  }

    6: client side

       1:  #include "iostream"
       2:   
       3:  #include <winsock2.h>
       4:  #include <windows.h>
       5:  using namespace std;
       6:  #pragma comment(lib, "Ws2_32")
       7:   
       8:   
       9:  int main()
      10:  {
      11:      WORD wVersionRequested;
      12:      WSADATA wsaData;
      13:      int err;
      14:      wVersionRequested = MAKEWORD(2,0);
      15:      err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
      16:      if(err != 0)
      17:      {
      18:           cout<<"socket init error."<< endl;
      19:      }
      20:      int i=0;
      21:      int iRet = 0;
      22:      SOCKET client;
      23:   
      24:      client = socket( AF_INET, SOCK_STREAM, 0); 
      25:      if( client == INVALID_SOCKET )
      26:      {
      27:          cout<< "socket() error"<<WSAGetLastError() <<endl;
      28:      }
      29:      SOCKADDR_IN        saServer;        
      30:   
      31:      memset(&saServer,0,sizeof(saServer));
      32:   
      33:      saServer.sin_family = AF_INET;
      34:      saServer.sin_addr.s_addr = inet_addr("127.0.0.1");
      35:      saServer.sin_port = htons(8000);
      36:      int nRet = connect(client,(sockaddr*)&saServer, sizeof(saServer));
      37:      if( iRet == SOCKET_ERROR)
      38:      {
      39:          cout<<"connect error"<<endl;
      40:          return 0;
      41:      }
      42:      else
      43:      {
      44:          cout<<"iRet:"<<iRet<<endl;
      45:          cout<<"connect success"<<WSAGetLastError()<<endl;
      46:      }
      47:       char buffer[128]={0};
      48:       while(1)
      49:       {
      50:           memset(buffer,0,128);
      51:           cout<<"input to send:";
      52:           cin>>buffer;
      53:           if(buffer[0] == 'q')
      54:              break;
      55:          int nBytes;
      56:   
      57:          if ((nBytes = send(client, buffer, strlen(buffer),0))
      58:              == SOCKET_ERROR)
      59:          {
      60:              if (GetLastError() == WSAEWOULDBLOCK) 
      61:              {
      62:                  printf("Blocking\n");
      63:                  Sleep(100);
      64:                  break;
      65:              }
      66:              else
      67:              {
      68:                  cout<<"send error:"<<GetLastError()<<endl;
      69:                  closesocket(client);
      70:                  break;
      71:              }
      72:          }
      73:          cout<<"send success .."<<endl;
      74:       }
      75:       WSACleanup();
      76:      return 0;
      77:  }
    Author:repository
    From:  http://repository.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    架构师图谱
    P3398 仓鼠找sugar
    NOIP 2017小凯的疑惑
    P2568 GCD
    自动AC机
    qbxt国庆刷题班 游记&总结
    【学习笔记】manacher算法
    [ZROI]分组
    BSGS与扩展BSGS
    Crt and ExCrt
  • 原文地址:https://www.cnblogs.com/repository/p/2196565.html
Copyright © 2011-2022 走看看