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:  }
posted @ 2011-09-30 15:06  Repository  阅读(642)  评论(0编辑  收藏  举报