采用IOCP技术的socket服务器代码,

 

  • #ifdef _DEBUG
    #define GMT_ASSERT(exp)  assert(exp)
    #else
    #define GMT_ASSERT(exp)
    #endif
    CRITICAL_SECTION CriticalSection;
    LPCTSTR LPSEND_DATA = "Hello, This is GMTServer"; // Test server sending data.
    #define IO_BUFSIZE 4096 * 2      // I/O buffer size.
    #define IP_BUFSIZE 32        // IP buffer size.
    typedef enum{ IOSEND, IORECV, IOQUIT } EIO_TYPE;
    typedef struct _SOCKET_INFORMATION
    {
     OVERLAPPED Overlapped;
     SOCKET      Socket;
     char        szIOBuffer[IO_BUFSIZE];
     WSABUF      DataBuf;
     EIO_TYPE eIoType;
     DWORD       dwIOBytes;
     char  szIp[IP_BUFSIZE];
     DWORD  dwPort;
     _SOCKET_INFORMATION()
     {
      memset(&Overlapped,0,sizeof(WSAOVERLAPPED));
      memset(szIOBuffer, 0, sizeof(szIOBuffer));
      DataBuf.buf = szIOBuffer;
      DataBuf.len = sizeof(szIOBuffer) - 1;
      eIoType = IOQUIT;
      dwIOBytes = 0;
      memset(szIp, 0, sizeof(szIp));
      dwPort = 0;
     }
    } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
    HANDLE g_hCompletePort = NULL;
    SOCKET g_ListenSocket = NULL; // Listenning socket.
    unsigned __stdcall IOThread(LPVOID pArguments);
    // Deliver send operation.
    // @ret 0 success or error code.
    int SendData(LPSOCKET_INFORMATION lpSI)
    {
     if (NULL == lpSI)
      return -1;
     if (INVALID_SOCKET == lpSI->Socket)
      return -1;
     int nRet = 0;
     DWORD dwFlags = 0;
     lpSI->dwIOBytes = 0;
     strcpy(lpSI->szIOBuffer, LPSEND_DATA);
     lpSI->DataBuf.buf = lpSI->szIOBuffer;
     lpSI->DataBuf.len = strlen(lpSI->szIOBuffer);
     lpSI->eIoType = IOSEND;
     if (WSASend(lpSI->Socket, &(lpSI->DataBuf), 1, &lpSI->dwIOBytes, dwFlags, &(lpSI->Overlapped), NULL) == SOCKET_ERROR)
     {
      nRet = WSAGetLastError();
      if (nRet != ERROR_IO_PENDING)
      {
       printf("WSASend() failed with error %d/n", nRet);
       if (0 == closesocket(lpSI->Socket))
       {
        lpSI->Socket = INVALID_SOCKET;
        delete lpSI;
        lpSI = NULL;
       }
      }
      else
       nRet = 0;
     }
     return nRet;
    }
    // Deliver recv operation.
    // @ret 0 success or error code.
    int RecvData(LPSOCKET_INFORMATION lpSI)
    {
     if (NULL == lpSI)
      return -1;
     if (INVALID_SOCKET == lpSI->Socket)
      return -1;
     int nRet = 0;
     DWORD dwFlags = 0;
     lpSI->eIoType = IORECV;
     memset(lpSI->szIOBuffer, 0, sizeof(lpSI->szIOBuffer));
     lpSI->DataBuf.len = sizeof(lpSI->szIOBuffer) - 1;
     lpSI->DataBuf.buf = lpSI->szIOBuffer;
     if (WSARecv(lpSI->Socket, &(lpSI->DataBuf), 1, &lpSI->dwIOBytes, &dwFlags, &(lpSI->Overlapped), NULL) == SOCKET_ERROR)
     {
      nRet = WSAGetLastError();
      if (nRet != ERROR_IO_PENDING)
      {
       printf("WSARecv() failed with error %d/n", nRet);
       if (0 == closesocket(lpSI->Socket))
       {
        lpSI->Socket = INVALID_SOCKET;
        delete lpSI;
        lpSI = NULL;
       }
      }
      else
       nRet = 0;
     }
     return nRet;
    }
    unsigned __stdcall IOThread(LPVOID lpArg)
    {
     int nRet;
     DWORD dwFlags;
     DWORD dwBytesTransferred = 0;
     LPSOCKET_INFORMATION lpSI = NULL;
     LPWSAOVERLAPPED lpOverlapped = NULL;
     while (TRUE)
     {
      //线程进入线程池,等待被唤醒
      lpSI = NULL;
      lpOverlapped = NULL;
      nRet = GetQueuedCompletionStatus(g_hCompletePort, &dwBytesTransferred, (PULONG_PTR)&lpSI, &lpOverlapped, INFINITE);
      if (nRet == 0 || dwBytesTransferred == 0)
      {
       if (closesocket(lpSI->Socket) == 0)
       {
        printf("GetQueuedCompletionStatus failed with error %d/n", GetLastError());
        lpSI->Socket = INVALID_SOCKET;
        delete lpSI;
        lpSI = NULL;
       }
       continue;
      }
      GMT_ASSERT(NULL != lpSI);
      lpSI->dwIOBytes = dwBytesTransferred;
      switch(lpSI->eIoType)
      {
      case IORECV:
       {
        EnterCriticalSection(&CriticalSection);
        // 输出代表数据处理
        printf("[%s:%d][%d]%s/n", lpSI->szIp, lpSI->dwPort, dwBytesTransferred, lpSI->szIOBuffer);
    //    Sleep(4000); //模拟处理时间
        LeaveCriticalSection(&CriticalSection);
        if (0 != SendData(lpSI))
         return 1;
        break;
       }
      case IOSEND:
       {
        if (0 != RecvData(lpSI))
         return 1;
        break;
       }
      case IOQUIT:
      default:
       break;
      }// switch
     }// while
     printf("IOThread is over/r/n");
     return 0;
    }
    // Listen ...
    // @ret 0 success or error code
    int Listen(LPCTSTR lpServerIp, DWORD dwPort)

     DWORD dwErr = 0;
     WSADATA wsaData;
     DWORD nRet = 0;
     nRet = WSAStartup(0x0202, &wsaData);
     if (nRet != 0)
     {
      printf("WSAStartup failed with error %d/n", nRet);
      return nRet;
     }
     InitializeCriticalSection(&CriticalSection);
     g_hCompletePort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
     if (NULL == g_hCompletePort)
     {
      dwErr = WSAGetLastError();
      printf("CreateIoCompletionPort failed with error %d", dwErr);
      WSACleanup();
      return dwErr;
     }
     //根据2倍于CPU个数+2来创建线程,以达到系统最佳性能
     SYSTEM_INFO SystemInfo;
     GetSystemInfo(&SystemInfo);
     unsigned threadID;
     for(unsigned int i=0; i<SystemInfo.dwNumberOfProcessors * 2+2; i++)
     {
      HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, &IOThread, NULL, 0, &threadID);
      if (hThread == NULL)
      {
       dwErr = GetLastError();
       printf("Create IOThread failed with error %d", dwErr);
       return dwErr;
      }
      CloseHandle(hThread);
     }
     g_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);
     if (INVALID_SOCKET == g_ListenSocket)
     {
      dwErr = WSAGetLastError();
      printf("WSASocket failed with error %d", dwErr);
      WSACleanup();
      return dwErr;
     }
     SOCKADDR_IN ServerAddr;
     memset(&ServerAddr, 0, sizeof(SOCKADDR_IN));
     ServerAddr.sin_family = AF_INET;
     if (lpServerIp == NULL)
      ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
     else
      ServerAddr.sin_addr.S_un.S_addr = inet_addr(lpServerIp);
     ServerAddr.sin_port = htons(dwPort);
     if (SOCKET_ERROR == bind(g_ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr)))
     {
      dwErr = WSAGetLastError();
      printf("bind failed with error %d", dwErr);
      WSACleanup();
      return dwErr;
     }
     if (SOCKET_ERROR == listen(g_ListenSocket, SOMAXCONN))
     {
      dwErr = WSAGetLastError();
      printf("listen failed with error %d", dwErr);
      WSACleanup();
      return dwErr;
     }
     printf("listenning.../n");
     // Accept connections and assign to the completion port.
     SOCKET AcceptSocket;
     while(TRUE)
     {
      printf("waiting for client connect./r/n");
      SOCKADDR_IN saClient;
      int nLen = sizeof(SOCKADDR_IN);
      memset(&saClient, 0, sizeof(SOCKADDR_IN));
      AcceptSocket = INVALID_SOCKET;
      AcceptSocket = WSAAccept(g_ListenSocket, (sockaddr *)&saClient, &nLen, NULL, 0);
      if (INVALID_SOCKET == AcceptSocket)
      {
       printf("WSAAccept() failed with error %d/n", WSAGetLastError());
       dwErr = WSAGetLastError();
       break;
      }  
      // Associate the accepted socket with the original completion port.
      LPSOCKET_INFORMATION pSI = new SOCKET_INFORMATION;
      pSI->Socket = AcceptSocket;
      strcpy(pSI->szIp, inet_ntoa(saClient.sin_addr));
      pSI->dwPort = saClient.sin_port;
      if (CreateIoCompletionPort((HANDLE) AcceptSocket, g_hCompletePort, (DWORD)pSI, 0) == NULL)
      {
       printf("CreateIoCompletionPort failed with error %d/n", GetLastError());
       dwErr = WSAGetLastError();
       break;
      }
      dwErr = RecvData(pSI);
      if (0 != dwErr) break; //Deliver recv operation.
     }
     DeleteCriticalSection(&CriticalSection);
     WSACleanup();
     printf("The main thread is over./n");
     return dwErr;
    }
    // Set sending file and recving file, listen ip and port.
    // @para lpSendFile  send file path, not use temporarily.
    //   lpRecvFile  recv file path, not use temporarily.
    //   lpServerIp  NULL any ip or specified ip.
    //   dwPort   listen port.
    //   dwSenInterval  send operation time interval, not use temporarily.
    //   dwRecvInterval Recv operation time interval, not use temporarily.
    //
    // @ret 0 success or error code.
    CMPLTIOSERVER_API int SetServer(LPCTSTR lpSendFile, LPCTSTR lpRecvFile, LPCTSTR lpServerIp, DWORD dwPort, DWORD dwSenInterval, DWORD dwRecvInternal)
    {
     return Listen(lpServerIp, dwPort);
    }
     
     
    // using
     PFUN pfun;
     HINSTANCE dllmodule = NULL;
     dllmodule=LoadLibrary("CmpltIOServer.dll");
     pfun=(PFUN)GetProcAddress(dllmodule,"SetServer");
     if (NULL == pfun)
     {
      DWORD dwErr = GetLastError();
      cout << "error code:" << dwErr << endl;
      return 1;
     }
     int nRet = pfun(NULL, NULL, g_szServer, g_dwPort, 2000, 4000);
     FreeLibrary(dllmodule);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值