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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Serialize and Deserialize Binary Tree
    sliding window substring problem汇总贴
    10. Regular Expression Matching
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接
    程序员如何写一份合格的简历?(附简历模版)
    9个提高代码运行效率的小技巧你知道几个?
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第六章 存储器层次结构
    24张图7000字详解计算机中的高速缓存
    《深入理解计算机系统》(CSAPP)实验四 —— Attack Lab
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第五章 优化程序性能
  • 原文地址:https://www.cnblogs.com/repository/p/2196565.html
Copyright © 2011-2022 走看看