一个IOCP例子

分类: WINDOWS






#include <winsock2.h>
 #include <mswsock.h>
 #include <windows.h>
 
#include <iostream>
 using namespace std;
 
int g_ThreadCount;
 HANDLE g_hIOCP = INVALID_HANDLE_VALUE;
 SOCKET g_ServerSocket = INVALID_SOCKET;
 
// Maximum Buffer Size
 #define MAX_BUFF_SIZE 8192
 
enum IO_OPERATION{IO_READ,IO_WRITE};
 
struct IO_DATA{
     WSAOVERLAPPED Overlapped;
     char Buffer[MAX_BUFF_SIZE];
     WSABUF wsabuf;
     int nTotalBytes;
     int nSentBytes;
     IO_OPERATION opCode;
     SOCKET activeSocket;
 };
 
DWORD WINAPI WorkerThread (LPVOID WorkThreadContext) {
     LPWSAOVERLAPPED lpOverlapped = NULL;
     IO_DATA *lpIOContext = NULL; 
    WSABUF buffSend;
     DWORD dwRecvNumBytes = 0;
     DWORD dwSendNumBytes = 0;
     DWORD dwFlags = 0;
     DWORD dwIoSize = 0;
        BOOL bSuccess = FALSE;
     int nRet = 0;
 
       while( 1 ) {
          void * lpCompletionKey = NULL;
          bSuccess = GetQueuedCompletionStatus(g_hIOCP, &dwIoSize,
                                              (LPDWORD)&lpCompletionKey,
                                              (LPOVERLAPPED *)&lpOverlapped, 
                                             INFINITE);
          if( !bSuccess )
          {
             cout << "GetQueuedCompletionStatus() failed:"<<GetLastError()<<endl;
             break;
          }
 
         lpIOContext = (IO_DATA *)lpOverlapped;
 
         if(dwIoSize == 0) //socket closed?
          {
              cout << "Client disconnect" << endl;
              closesocket(lpIOContext->activeSocket);
              delete lpIOContext;
              continue;
          }
 
         if(lpIOContext->opCode == IO_READ) // a read operation complete
          {
                 lpIOContext->nTotalBytes = lpIOContext->wsabuf.len;
                 lpIOContext->nSentBytes = 0;
                 lpIOContext->opCode = IO_WRITE;
                 dwFlags = 0;
                 nRet = WSASend(
                               lpIOContext->activeSocket,
                               &lpIOContext->wsabuf, 1, &dwSendNumBytes,
                               dwFlags,
                               &(lpIOContext->Overlapped), NULL);
                 if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                         cout << "WASSend Failed::Reason Code::"<< WSAGetLastError() << endl;
                         closesocket(lpIOContext->activeSocket);
                         delete lpIOContext;
                         continue;
                 }
          }
          else if(lpIOContext->opCode == IO_WRITE) //a write operation complete
          {
                 lpIOContext->nSentBytes += dwIoSize;
                 dwFlags = 0;
                 if( lpIOContext->nSentBytes < lpIOContext->nTotalBytes ) {
                     lpIOContext->opCode = IO_WRITE;
                     // A Write operation has not completed yet, so post another
                     // Write operation to post remaining data.
                     buffSend.buf = lpIOContext->Buffer + lpIOContext->nSentBytes;
                     buffSend.len = lpIOContext->nTotalBytes - lpIOContext->nSentBytes;
                     nRet = WSASend (
                                    lpIOContext->activeSocket,
                                    &buffSend, 1, &dwSendNumBytes,
                                    dwFlags,
                                    &(lpIOContext->Overlapped), NULL);
 
                    if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                         cout << "WASSend Failed::Reason Code::"<< WSAGetLastError() << endl;
                         closesocket(lpIOContext->activeSocket);
                         delete lpIOContext;
                         continue;
                     }
                 } else {
                     // Write operation completed, so post Read operation.
                     lpIOContext->opCode = IO_READ; 
                    dwRecvNumBytes = 0;
                     dwFlags = 0;
                     lpIOContext->wsabuf.buf = lpIOContext->Buffer,
                     ZeroMemory(lpIOContext->wsabuf.buf,MAX_BUFF_SIZE);
                     lpIOContext->Overlapped.Internal = 0;
                     lpIOContext->Overlapped.InternalHigh = 0;
                     lpIOContext->Overlapped.Offset = 0;
                     lpIOContext->Overlapped.OffsetHigh = 0;
                     lpIOContext->Overlapped.hEvent = NULL;
                     lpIOContext->wsabuf.len = MAX_BUFF_SIZE;
                     nRet = WSARecv(
                                   lpIOContext->activeSocket,
                                   &lpIOContext->wsabuf, 1, &dwRecvNumBytes,
                                   &dwFlags,
                                   &lpIOContext->Overlapped, NULL);
                     if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                         cout << "WASRecv Failed::Reason Code::"<< WSAGetLastError() << endl;
                         closesocket(lpIOContext->activeSocket);
                         delete lpIOContext;
                         continue;
                     } 
                }
          }
     }
     return 0;
 }
 
void main (int argc, char * argv[])
 {
     { // Init winsock2
         WSADATA wsaData;
         ZeroMemory(&wsaData,sizeof(WSADATA));
         int retVal = -1;
         if( (retVal = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0 ) {
             cout << "WSAStartup Failed::Reason Code::"<< retVal << endl;
             return;
         }
     }
 
    { //Create socket
         g_ServerSocket = WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, NULL,0,WSA_FLAG_OVERLAPPED);
 
        if( g_ServerSocket == INVALID_SOCKET ) {
             cout << "Server Socket Creation Failed::Reason Code::" << WSAGetLastError() << endl;
             return;
         }
     }
 
    { //bind
         sockaddr_in service;
         service.sin_family = AF_INET;
         service.sin_addr.s_addr = htonl(INADDR_ANY);
         service.sin_port = htons(5000);
         int retVal = bind(g_ServerSocket,(SOCKADDR *)&service,sizeof(service));
         if( retVal == SOCKET_ERROR ) {
             cout << "Server Soket Bind Failed::Reason Code::"<< WSAGetLastError() << endl;
             return;
         }
     }
 
    { //listen
         int retVal = listen(g_ServerSocket, 8);
         if( retVal == SOCKET_ERROR ) {
             cout << "Server Socket Listen Failed::Reason Code::"<< WSAGetLastError() << endl;
             return;
         }
     }
 
    { // Create IOCP
         SYSTEM_INFO sysInfo;
         ZeroMemory(&sysInfo,sizeof(SYSTEM_INFO));
         GetSystemInfo(&sysInfo);
         g_ThreadCount = sysInfo.dwNumberOfProcessors * 1;
         g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,g_ThreadCount);
         if (g_hIOCP == NULL) {
             cout << "CreateIoCompletionPort() Failed::Reason::"<< GetLastError() << endl;
             return;
         }
 
           if (CreateIoCompletionPort((HANDLE)g_ServerSocket,g_hIOCP,0,0) == NULL){
             cout << "Binding Server Socket to IO Completion Port Failed::Reason Code::"<< GetLastError() << endl;
             return ;
         }
     }
 
    { //Create worker threads
         for( DWORD dwThread=0; dwThread < g_ThreadCount; dwThread++ )
         {
             HANDLE hThread;
             DWORD dwThreadId;
 
            hThread = CreateThread(NULL, 0, WorkerThread, 0, 0, &dwThreadId);
             CloseHandle(hThread);
         }
     }
 
    { //accept new connection
         while(1)
         {
             SOCKET ls = accept( g_ServerSocket, NULL, NULL );
             if(ls == SOCKET_ERROR) break;
             cout << "Client connected." << endl;
 
            { //diable buffer to improve performance
                 int nZero = 0;
                 setsockopt(ls, SOL_SOCKET, SO_SNDBUF, (char *)&nZero, sizeof(nZero));
             }
 
            if (CreateIoCompletionPort((HANDLE)ls,g_hIOCP,0,0) == NULL){
                 cout << "Binding Client Socket to IO Completion Port Failed::Reason Code::"<< GetLastError() << endl;
                 closesocket(ls);
             }
             else { //post a recv request
                 IO_DATA * data = new IO_DATA;
                 ZeroMemory(&data->Overlapped,sizeof(data->Overlapped));
                 ZeroMemory(data->Buffer,sizeof(data->Buffer));
                 data->opCode = IO_READ;
                 data->nTotalBytes = 0;
                 data->nSentBytes = 0;
                 data->wsabuf.buf = data->Buffer;
                 data->wsabuf.len = sizeof(data->Buffer);
                 data->activeSocket = ls;
                 DWORD dwRecvNumBytes=0,dwFlags=0;
                 int nRet = WSARecv(ls,&data->wsabuf, 1, &dwRecvNumBytes,
                                   &dwFlags,
                                   &data->Overlapped, NULL);
                 if(nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
                     cout << "WASRecv Failed::Reason Code::"<< WSAGetLastError() << endl;
                     closesocket(ls);
                     delete data;
                 }
             }
         }
     }
 
    closesocket(g_ServerSocket);
     WSACleanup();
 }
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值