Winsock IOCP模型

http://blog.csdn.net/visualeleven/article/details/6041893


  1. // IOCP.cpp : Defines the entry point for the console application.  
  2. //  
  3. //  
  4.   
  5. #include "stdafx.h"  
  6.   
  7. #include <WinSock2.h>  
  8. #include <Windows.h>  
  9. #include <process.h>  
  10. #pragma comment(lib, "WS2_32.lib")  
  11.   
  12. #define MAX_BUFFER  256  
  13. #define MAX_TIMEOUT 1000  
  14. #define MAX_SOCKET  1024  
  15. #define MAX_THREAD  64  
  16.   
  17. typedef enum _OPERATION_INFO_  
  18. {  
  19.     OP_NULL,  
  20.     OP_READ,  
  21.     OP_WRITE  
  22. }OPERATIONINFO;  
  23.   
  24. typedef struct _PER_HANDLE_DATA_  
  25. {  
  26. public:  
  27.     _PER_HANDLE_DATA_()  
  28.     {  
  29.         clean();  
  30.     }  
  31.     ~_PER_HANDLE_DATA_()  
  32.     {  
  33.         clean();  
  34.     }  
  35. protected:  
  36.     void clean()  
  37.     {  
  38.         sock = INVALID_SOCKET;  
  39.         memset(&addr, 0, sizeof(addr));  
  40.         addr.sin_addr.S_un.S_addr = INADDR_ANY;  
  41.         addr.sin_port = htons(0);  
  42.         addr.sin_family = AF_INET;  
  43.     }  
  44. public:   
  45.     SOCKET sock;  
  46.     SOCKADDR_IN addr;  
  47.       
  48. }PERHANDLEDATA, *PPERHANDLEDATA;  
  49.   
  50. typedef struct _PER_IO_DTATA_  
  51. {  
  52. public:   
  53.     _PER_IO_DTATA_()  
  54.     {  
  55.         clean();  
  56.     }  
  57.     ~_PER_IO_DTATA_()  
  58.     {  
  59.         clean();  
  60.     }  
  61. private:  
  62.     void clean()  
  63.     {  
  64.         ZeroMemory(&ol, sizeof(ol));  
  65.         memset(buf, 0, sizeof(buf));  
  66.         wsaBuf.buf = buf;  
  67.         wsaBuf.len = MAX_BUFFER;  
  68.         opType =  OP_NULL;  
  69.     }  
  70. public:  
  71.     WSAOVERLAPPED ol;  
  72.     WSABUF wsaBuf;  
  73.     char buf[MAX_BUFFER];  
  74.     OPERATIONINFO opType;  
  75. }PERIODATA, *PPERIODATA;  
  76.   
  77. HANDLE hThread[MAX_THREAD] = {0};  
  78. int g_nThread = 0;  
  79. BOOL g_bExitThread = FALSE;  
  80.   
  81. unsigned __stdcall ThreadProc(LPVOID lParam);  
  82.   
  83. int _tmain(int argc, _TCHAR* argv[])  
  84. {  
  85.     WSADATA wsaData;  
  86.     if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))  
  87.     {  
  88.         printf("WSAStartup failed with error code: %d/n", GetLastError());  
  89.         return EXIT_FAILURE;  
  90.     }  
  91.     if(2 != HIBYTE(wsaData.wVersion) || 2 != LOBYTE(wsaData.wVersion))  
  92.     {  
  93.         printf("Socket version not supported./n");  
  94.         WSACleanup();  
  95.         return EXIT_FAILURE;  
  96.     }  
  97.   
  98.     // Create I/O Completion Port  
  99.     HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);  
  100.     if(NULL == hIOCP)  
  101.     {  
  102.         printf("CreateIoCompletionPort failed with error code: %d/n", GetLastError());  
  103.         WSACleanup();  
  104.         return EXIT_FAILURE;  
  105.     }  
  106.     // Create worker thread  
  107.     SYSTEM_INFO si = {0};  
  108.     GetSystemInfo(&si);  
  109.     for(int i = 0; i < (int)si.dwNumberOfProcessors+2; i++)  
  110.     {  
  111.         hThread[g_nThread] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (LPVOID)hIOCP, 0, NULL);  
  112.         if(NULL == hThread[g_nThread])  
  113.         {  
  114.             printf("_beginthreadex failed with error code: %d/n", GetLastError());  
  115.             continue;  
  116.         }  
  117.         ++g_nThread;  
  118.   
  119.         if(g_nThread > MAX_THREAD)  
  120.         {  
  121.             break;  
  122.         }  
  123.     }  
  124.   
  125.     // Create socket  
  126.     SOCKET sListen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);  
  127.     if(INVALID_SOCKET == sListen)  
  128.     {  
  129.         printf("WSASocket failed with error code: %d/n", WSAGetLastError());  
  130.         goto EXIT_CODE;  
  131.     }  
  132.     SOCKADDR_IN addr;  
  133.     memset(&addr, 0, sizeof(addr));  
  134.     addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  
  135.     addr.sin_family = AF_INET;  
  136.     addr.sin_port = htons(5050);  
  137.     if(SOCKET_ERROR == bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)))  
  138.     {  
  139.         printf("bind failed with error code: %d/n", WSAGetLastError());  
  140.         closesocket(sListen);  
  141.         sListen = INVALID_SOCKET;  
  142.         goto EXIT_CODE;  
  143.     }  
  144.     if(SOCKET_ERROR == listen(sListen, 5))  
  145.     {  
  146.         printf("listen failed with error code: %d/n", WSAGetLastError());  
  147.         closesocket(sListen);  
  148.         sListen = INVALID_SOCKET;  
  149.         goto EXIT_CODE;  
  150.     }  
  151.   
  152.     printf("Server start, wait for client to connect .../n");  
  153.     while(TRUE)  
  154.     {  
  155.         SOCKADDR_IN remote;  
  156.         memset(&remote, 0, sizeof(remote));  
  157.         int len = sizeof(remote);  
  158.   
  159.         SOCKET sNew = WSAAccept(sListen, (LPSOCKADDR)&remote, &len, NULL, NULL);  
  160.         if(INVALID_SOCKET == sNew)  
  161.         {  
  162.             printf("WSAAccept failed with error code: %d/n", WSAGetLastError());  
  163.             continue;  
  164.         }  
  165.         printf("Client <%s : %d> come in./n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));  
  166.         PERHANDLEDATA* pPerHandleData = new PERHANDLEDATA;  
  167.         pPerHandleData->sock = sNew;       
  168.         memcpy(&(pPerHandleData->addr), &remote, sizeof(remote));  
  169.         // Associate with IOCP  
  170.         if(NULL == CreateIoCompletionPort((HANDLE)(pPerHandleData->sock), hIOCP, (ULONG_PTR)pPerHandleData, 0))  
  171.         {  
  172.             printf("CreateIoCompletionPort failed with error code: %d/n", GetLastError());  
  173.             closesocket(pPerHandleData->sock);  
  174.             delete pPerHandleData;  
  175.             continue;  
  176.         }  
  177.         // Post Receive  
  178.         PERIODATA* pPerIoData = new PERIODATA;  
  179.         pPerIoData->opType = OP_READ;  
  180.         DWORD dwTrans = pPerIoData->wsaBuf.len;  
  181.         DWORD dwFlags = 0;  
  182.         if(SOCKET_ERROR == WSARecv(pPerHandleData->sock, &(pPerIoData->wsaBuf), 1,   
  183.             &dwTrans, &dwFlags, &(pPerIoData->ol), NULL))  
  184.         {  
  185.             if(WSA_IO_PENDING != WSAGetLastError())  
  186.             {  
  187.                 printf("WSARecv failed with error code: %d/n", WSAGetLastError());  
  188.                 closesocket(pPerHandleData->sock);  
  189.                 delete pPerHandleData;  
  190.                 delete pPerIoData;  
  191.                 continue;  
  192.             }  
  193.         }  
  194.     }  
  195.     closesocket(sListen);  
  196.     sListen = INVALID_SOCKET;  
  197.   
  198. EXIT_CODE:  
  199.     g_bExitThread = TRUE;  
  200.     PostQueuedCompletionStatus(hIOCP, 0, NULL, NULL);  
  201.     WaitForMultipleObjects(g_nThread, hThread, TRUE, INFINITE);  
  202.     for(int i = 0; i < g_nThread; i++)  
  203.     {  
  204.         CloseHandle(hThread[g_nThread]);  
  205.     }  
  206.     CloseHandle(hIOCP); // Close IOCP  
  207.     WSACleanup();  
  208.     return 0;  
  209. }  
  210.   
  211. unsigned __stdcall ThreadProc(LPVOID lParam)  
  212. {  
  213.     HANDLE hIOCP = (HANDLE)lParam;  
  214.   
  215.     PERHANDLEDATA* pPerHandleData = NULL;  
  216.     PERIODATA* pPerIoData = NULL;  
  217.     WSAOVERLAPPED* lpOverlapped = NULL;  
  218.     DWORD dwTrans = 0;  
  219.     DWORD dwFlags = 0;  
  220.     while(!g_bExitThread)  
  221.     {  
  222.         BOOL bRet = GetQueuedCompletionStatus(hIOCP, &dwTrans, (PULONG_PTR)&pPerHandleData, &lpOverlapped, INFINITE);  
  223.         if(!bRet)  
  224.         {  
  225.             printf("GetQueuedCompletionStatus failed with error: %d/n", WSAGetLastError());  
  226.             continue;  
  227.         }  
  228.         else  
  229.         {  
  230.             pPerIoData = CONTAINING_RECORD(lpOverlapped, PERIODATA, ol);  
  231.             if(0 == dwTrans)  
  232.             {  
  233.                 printf("Client: <%s : %d> leave./n", inet_ntoa(pPerHandleData->addr.sin_addr), ntohs(pPerHandleData->addr.sin_port));  
  234.                 closesocket(pPerHandleData->sock);  
  235.                 delete pPerHandleData;  
  236.                 delete pPerIoData;  
  237.                 continue;  
  238.             }  
  239.             else  
  240.             {  
  241.                 switch(pPerIoData->opType)  
  242.                 {  
  243.                 case OP_READ:  
  244.                     printf("recv client <%s : %d> data: %s/n", inet_ntoa(pPerHandleData->addr.sin_addr), ntohs(pPerHandleData->addr.sin_port), pPerIoData->buf);  
  245.                     pPerIoData->opType = OP_WRITE;  
  246.                     memset(&(pPerIoData->ol), 0, sizeof(pPerIoData->ol));  
  247.                     if(SOCKET_ERROR == WSASend(pPerHandleData->sock, &(pPerIoData->wsaBuf), 1, &dwTrans, dwFlags, &(pPerIoData->ol), NULL))  
  248.                     {  
  249.                         if(WSA_IO_PENDING != WSAGetLastError())  
  250.                         {  
  251.                             printf("WSASend failed with error code: %d./n", WSAGetLastError());  
  252.                             continue;  
  253.                         }  
  254.                     }  
  255.                     break;  
  256.   
  257.                 case OP_WRITE:  
  258.                     {  
  259.                         pPerIoData->opType = OP_READ;  
  260.                         dwFlags = 0;  
  261.                         memset(&(pPerIoData->ol), 0, sizeof(pPerIoData->ol));  
  262.                         memset(pPerIoData->buf, 0, sizeof(pPerIoData->buf));  
  263.                         pPerIoData->wsaBuf.buf = pPerIoData->buf;  
  264.                         dwTrans = pPerIoData->wsaBuf.len = MAX_BUFFER;  
  265.                         if(SOCKET_ERROR == WSARecv(pPerHandleData->sock, &(pPerIoData->wsaBuf), 1, &dwTrans, &dwFlags, &(pPerIoData->ol), NULL))  
  266.                         {  
  267.                             if(WSA_IO_PENDING != WSAGetLastError())  
  268.                             {  
  269.                                 printf("WSARecv failed with error code: %d./n", WSAGetLastError());  
  270.                                 continue;  
  271.                             }  
  272.                         }  
  273.                     }  
  274.                     break;  
  275.   
  276.                 default:  
  277.                     break;  
  278.                 }  
  279.             }  
  280.         }  
  281.     }  
  282.     return 0;  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值