【网络编程】之十二、wsaeventselect+线程池 服务器实现

[cpp]  view plain copy
  1. #include<WinSock2.h>  
  2. #include<iostream>  
  3. using namespace std;  
  4.   
  5.   
  6. #pragma comment(lib, "WS2_32.lib")  
  7.   
  8. typedef struct _SOCKET_OBJ{  
  9.     SOCKET s;  
  10.     HANDLE event;  
  11.     sockaddr_in addrRemote;  
  12.     _SOCKET_OBJ *pNext;  
  13. }SOCKET_OBJ, *PSOCKET_OBJ;  
  14.   
  15. typedef struct _THREAD_OBJ{  
  16.     HANDLE events[WSA_MAXIMUM_WAIT_EVENTS];  
  17.     int nSocketCount;  
  18.     PSOCKET_OBJ pSocketHeader;  
  19.     PSOCKET_OBJ pSocketTail;  
  20.     CRITICAL_SECTION cs;  
  21.     _THREAD_OBJ *pNext;  
  22. }THREAD_OBJ, *PTHREAD_OBJ;  
  23.   
  24. PTHREAD_OBJ g_pThreadList;  
  25. CRITICAL_SECTION g_cs;  
  26.   
  27. LONG g_nTatolConnections;  
  28. LONG g_nCurrentConnections;  
  29.   
  30. DWORD WINAPI ServerThread(LPVOID lpParam);  
  31. //******************************************************************************//  
  32. PSOCKET_OBJ GetSocketObj(SOCKET s)  
  33. {  
  34.     PSOCKET_OBJ pSocket = (PSOCKET_OBJ)::GlobalAlloc(GPTR, sizeof(SOCKET_OBJ));  
  35.     if(pSocket != NULL)  
  36.     {  
  37.         pSocket->s = s;  
  38.         pSocket->event = ::WSACreateEvent();  
  39.     }  
  40.   
  41.     return pSocket;  
  42. }  
  43.   
  44. void FreeSocketObj(PSOCKET_OBJ pSocket)  
  45. {  
  46.     ::CloseHandle(pSocket->event);  
  47.     if(pSocket->s != INVALID_SOCKET)  
  48.     {  
  49.         closesocket(pSocket->s);  
  50.     }  
  51.     ::GlobalFree(pSocket);  
  52. }  
  53.   
  54. //*************************************************************************//  
  55.   
  56. PTHREAD_OBJ GetThreadObj()  
  57. {  
  58.     PTHREAD_OBJ pThread = (PTHREAD_OBJ)::GlobalAlloc(GPTR, sizeof(THREAD_OBJ));  
  59.     if(pThread != NULL)  
  60.     {  
  61.         ::InitializeCriticalSection(&pThread->cs);  
  62.   
  63.         pThread->events[0] = ::WSACreateEvent();  
  64.   
  65.         ::EnterCriticalSection(&g_cs);  
  66.         pThread->pNext = g_pThreadList;  
  67.         g_pThreadList = pThread;  
  68.         ::LeaveCriticalSection(&g_cs);  
  69.     }  
  70.   
  71.     return pThread;  
  72. }  
  73.   
  74. void FreeThreadObj(PTHREAD_OBJ pThread)  
  75. {  
  76.     ::EnterCriticalSection(&g_cs);  
  77.     PTHREAD_OBJ p = g_pThreadList;  
  78.     if(p == pThread)  
  79.     {  
  80.         g_pThreadList = p->pNext;  
  81.     }  
  82.     else  
  83.     {  
  84.         while(p != NULL && p->pNext != pThread)  
  85.         {  
  86.             p = p->pNext;  
  87.         }  
  88.         if(p != NULL)  
  89.         {  
  90.             p->pNext = pThread->pNext;  
  91.         }  
  92.     }  
  93.     ::LeaveCriticalSection(&g_cs);  
  94.   
  95.     ::CloseHandle(pThread->events[0]);  
  96.     ::DeleteCriticalSection(&pThread->cs);  
  97.     ::GlobalFree(pThread);  
  98. }  
  99.   
  100.   
  101. void RebulidArray(PTHREAD_OBJ pThread)  
  102. {  
  103.     ::EnterCriticalSection(&pThread->cs);  
  104.     PSOCKET_OBJ pSocket = pThread->pSocketHeader;  
  105.     int n = 1;  
  106.     while(pSocket != NULL)  
  107.     {  
  108.         pThread->events[n++] = pSocket->event;  
  109.         pSocket = pSocket->pNext;  
  110.     }  
  111.   
  112.     ::LeaveCriticalSection(&pThread->cs);  
  113. }  
  114.   
  115. //********************************************************************//  
  116.   
  117. BOOL insertSocketObj(PTHREAD_OBJ pThread, PSOCKET_OBJ pSocket)  
  118. {  
  119.     BOOL bRet = FALSE;  
  120.     ::EnterCriticalSection(&pThread->cs);  
  121.     if(pThread->nSocketCount < WSA_MAXIMUM_WAIT_EVENTS - 1)  
  122.     {  
  123.         if(pThread->pSocketHeader == NULL)  
  124.         {  
  125.             pThread->pSocketHeader = pThread->pSocketTail = pSocket;  
  126.         }  
  127.         else  
  128.         {  
  129.             pThread->pSocketTail->pNext = pSocket;  
  130.             pThread->pSocketTail = pSocket;  
  131.         }  
  132.         pThread->nSocketCount++;  
  133.         bRet = TRUE;  
  134.     }  
  135.   
  136.     ::LeaveCriticalSection(&pThread->cs);  
  137.   
  138.     if(bRet)  
  139.     {  
  140.         ::InterlockedIncrement(&g_nTatolConnections);  
  141.         ::InterlockedIncrement(&g_nCurrentConnections);  
  142.     }  
  143.     return bRet;  
  144. }  
  145.   
  146. void AssignToFreeThread(PSOCKET_OBJ pSocket)  
  147. {  
  148.     pSocket->pNext = NULL;  
  149.     ::EnterCriticalSection(&g_cs);  
  150.     PTHREAD_OBJ pThread = g_pThreadList;  
  151.   
  152.     while(pThread != NULL)  
  153.     {  
  154.         if(insertSocketObj(pThread, pSocket))  
  155.             break;  
  156.         pThread = pThread->pNext;  
  157.     }  
  158.   
  159.   
  160.     if(pThread == NULL)  
  161.     {  
  162.         pThread = GetThreadObj();  
  163.         insertSocketObj(pThread, pSocket);  
  164.         ::CreateThread(NULL, 0, ServerThread, pThread, 0, NULL);  
  165.   
  166.     }  
  167.   
  168.     ::LeaveCriticalSection(&g_cs);  
  169.   
  170.     ::WSASetEvent(pThread->events[0]);  
  171. }  
  172.   
  173.   
  174. void RemoveSocketObj(PTHREAD_OBJ pThread, PSOCKET_OBJ pSocket)  
  175. {  
  176.     ::EnterCriticalSection(&pThread->cs);  
  177.   
  178.     PSOCKET_OBJ pTest = pThread->pSocketHeader;  
  179.     if(pTest == pSocket)  
  180.     {  
  181.         if(pThread->pSocketHeader == pThread->pSocketTail)  
  182.             pThread->pSocketTail = pThread->pSocketHeader = pTest->pNext;  
  183.         else  
  184.             pThread->pSocketHeader = pTest->pNext;  
  185.     }  
  186.     else  
  187.     {  
  188.         while(pTest != NULL && pTest->pNext != pSocket)  
  189.             pTest = pTest->pNext;  
  190.         if(pTest != NULL)  
  191.         {  
  192.             if(pThread->pSocketTail == pSocket)  
  193.                 pThread->pSocketTail = pTest;  
  194.             pTest->pNext = pSocket->pNext;  
  195.         }  
  196.     }  
  197.   
  198.     pThread->nSocketCount--;  
  199.   
  200.     ::LeaveCriticalSection(&pThread->cs);  
  201.   
  202.   
  203.     ::WSASetEvent(pThread->events[0]);  
  204.     ::InterlockedDecrement(&g_nCurrentConnections);  
  205. }  
  206.   
  207. //********************************************************************//  
  208. PSOCKET_OBJ FindSocketObj(PTHREAD_OBJ pThread, int nIndex)  
  209. {  
  210.     PSOCKET_OBJ pSocket = pThread->pSocketHeader;  
  211.     while(--nIndex)  
  212.     {  
  213.         if(pSocket == NULL)  
  214.             return NULL;  
  215.         pSocket = pSocket->pNext;  
  216.     }  
  217.     return pSocket;  
  218. }  
  219.   
  220. BOOL HandleIO(PTHREAD_OBJ pThread, PSOCKET_OBJ pSocket)  
  221. {  
  222.     WSANETWORKEVENTS event;  
  223.     ::WSAEnumNetworkEvents(pSocket->s, pSocket->event, &event);  
  224.     do{  
  225.         if(event.lNetworkEvents & FD_READ)  
  226.         {  
  227.             if(event.iErrorCode[FD_READ_BIT] == 0)  
  228.             {  
  229.                 char szText[256];  
  230.                 int nRecv = ::recv(pSocket->s, szText, strlen(szText), 0);  
  231.                 if(nRecv > 0)  
  232.                 {  
  233.                     szText[nRecv] = '\0';  
  234.                     cout << "接收到数据:" << szText << endl;  
  235.                 }  
  236.             }  
  237.             else  
  238.                 break;  
  239.         }  
  240.         else  
  241.         {  
  242.             if(event.lNetworkEvents &FD_CLOSE)  
  243.             {  
  244.                 break;  
  245.             }  
  246.             else  
  247.             {  
  248.                 if(event.lNetworkEvents & FD_WRITE)  
  249.                 {  
  250.                     if(event.iErrorCode[FD_READ_BIT] == 0)  
  251.                     {  
  252.                         char szText[256];  
  253.                         int nRecv = ::recv(pSocket->s, szText, strlen(szText), 0);  
  254.                         if(nRecv > 0)  
  255.                         {  
  256.                             szText[nRecv] = '\0';  
  257.                             cout << "接收到数据:" << szText << endl;  
  258.                         }  
  259.                     }  
  260.                     else  
  261.                         break;  
  262.                 }  
  263.             }  
  264.         }  
  265.         return TRUE;  
  266.   
  267.     }while(FALSE);  
  268.   
  269.   
  270.     RemoveSocketObj(pThread, pSocket);  
  271.     FreeSocketObj(pSocket);  
  272.     return FALSE;  
  273. }  
  274.   
  275.   
  276. DWORD WINAPI ServerThread(LPVOID lpParam)  
  277. {  
  278.     PTHREAD_OBJ pThread = (PTHREAD_OBJ)lpParam;  
  279.     while(TRUE)  
  280.     {  
  281.         int nIndex = ::WSAWaitForMultipleEvents(pThread->nSocketCount + 1, pThread->events, FALSE, WSA_INFINITE, FALSE);  
  282.         nIndex = nIndex - WSA_WAIT_EVENT_0;  
  283.   
  284.         for(int i = nIndex; i < pThread->nSocketCount + 1; ++i)  
  285.         {  
  286.             nIndex = ::WSAWaitForMultipleEvents(1, &pThread->events[i], TRUE, 1000, FALSE);  
  287.             if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT)  
  288.             {  
  289.                 continue;  
  290.             }  
  291.             else  
  292.             {  
  293.                 if(i == 0)  
  294.                 {  
  295.                     RebulidArray(pThread);  
  296.   
  297.                     if(pThread->nSocketCount == 0)  
  298.                     {  
  299.                         FreeThreadObj(pThread);  
  300.                         return 0;  
  301.                     }  
  302.                     ::WSAResetEvent(pThread->events[0]);  
  303.                 }  
  304.                 else  
  305.                 {  
  306.                     PSOCKET_OBJ pSocket = (PSOCKET_OBJ)FindSocketObj(pThread, i);  
  307.                     if(pSocket != NULL)  
  308.                     {  
  309.                         if(!HandleIO(pThread, pSocket))  
  310.                             RebulidArray(pThread);  
  311.                     }  
  312.                     else  
  313.                         cout << "Unable to find socket object" << endl;  
  314.                 }  
  315.             }  
  316.         }  
  317.     }  
  318.     return 0;  
  319. }  
  320.   
  321.   
  322. //******************************************************************************//  
  323.   
  324. int main(void)  
  325. {  
  326.   
  327.     WSADATA wsaData;    
  328.     WORD sockVersion = MAKEWORD(2,0);//指定版本号    
  329.     ::WSAStartup(sockVersion, &wsaData);//载入winsock的dll    
  330.     //创建套接字基于TCP    
  331.     SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
  332.     if(sListen == INVALID_SOCKET)    
  333.     {    
  334.         printf("error");    
  335.         ::WSACleanup();//清理,释放资源    
  336.         return 0;    
  337.     }    
  338.   
  339.     sockaddr_in sin;    
  340.     sin.sin_family = AF_INET;    
  341.     sin.sin_port = htons(8888);//端口号8888    
  342.     sin.sin_addr.S_un.S_addr = INADDR_ANY;//地址全是0,也就是所有的地址    
  343.     //绑定socket    
  344.     if(::bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)    
  345.     {    
  346.         printf("error");    
  347.         ::WSACleanup();//清理释放资源    
  348.         return 0;    
  349.     }    
  350.     //监听socket    
  351.     if(::listen(sListen, 2) == SOCKET_ERROR)    
  352.     {    
  353.         printf("error");    
  354.         ::WSACleanup();//释放资源    
  355.         return 0;    
  356.     }    
  357.   
  358.     WSAEVENT event = ::WSACreateEvent();  
  359.     ::WSAEventSelect(sListen, event, FD_ACCEPT | FD_CLOSE);  
  360.     ::InitializeCriticalSection(&g_cs);  
  361.   
  362.     //处理请求  
  363.     while(TRUE)  
  364.     {  
  365.         int nRet = ::WaitForSingleObject(event, 5 * 1000);  
  366.         if(nRet == WAIT_FAILED)  
  367.         {  
  368.             cout << "failed waitforsingleobject" << endl;  
  369.             break;  
  370.         }  
  371.         else if(nRet == WSA_WAIT_TIMEOUT)  
  372.         {  
  373.             cout << endl;  
  374.             cout << " tatolconnections:" << g_nTatolConnections << endl;  
  375.             cout << " currentconnections: " << g_nCurrentConnections << endl;  
  376.             continue;  
  377.         }  
  378.         else  
  379.         {  
  380.             ::ResetEvent(event);   //新连接  
  381.   
  382.             while(TRUE)  
  383.             {  
  384.                 sockaddr_in si;  
  385.                 int nLen = sizeof(si);  
  386.                 SOCKET sNew = ::accept(sListen, (sockaddr*)&si, &nLen);  
  387.                 if(sNew == SOCKET_ERROR)  
  388.                     break;  
  389.                 PSOCKET_OBJ pSocket = GetSocketObj(sNew);  
  390.                 pSocket->addrRemote = si;  
  391.                 ::WSAEventSelect(pSocket->s, pSocket->event, FD_READ | FD_CLOSE | FD_WRITE);  
  392.                 AssignToFreeThread(pSocket);  
  393.             }  
  394.         }  
  395.     }  
  396.   
  397.     ::DeleteCriticalSection(&g_cs);  
  398.     ::WSACleanup();  
  399.     return 0;  
  400. }  

版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值