重叠IO之事件通知模型

    技术2025-08-22  9

    /***********************************************************************   Author: JMF*   Version:1.0*   BUG: 最大只允许同时64个客户端同时连接(WSA_MAXIMUM_WAIT_EVENTS)***********************************************************************/#include <winsock2.h>#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <assert.h>

    #pragma comment(lib,"Ws2_32.lib")

    #define SERVER_ADDR "192.168.168.152"#define PORT    3000#define MAX_CONNECT 5#define MSG_SIZE   1024

    typedef struct tagOlData{OVERLAPPED ol;WSABUF   wb;char   buff[MSG_SIZE];DWORD       dwRecv;DWORD   dwFlag;}OlData,*pOlData;

    typedef pOlData LPOldData;

    SOCKET   g_Socket[WSA_MAXIMUM_WAIT_EVENTS] = {0};WSAEVENT g_Event[WSA_MAXIMUM_WAIT_EVENTS] = {0};DWORD   g_dwNum = 0;LPOldData   g_OleData[WSA_MAXIMUM_WAIT_EVENTS] = {0};

    DWORD WINAPI ThreadProc(LPVOID lpPara);

    int main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 )      return EXIT_FAILURE; if ( LOBYTE( wsaData.wVersion ) != 2 ||        HIBYTE( wsaData.wVersion ) != 2 ) {     WSACleanup( );   return EXIT_FAILURE; }SOCKET sock = socket(AF_INET,SOCK_STREAM,0);assert(sock != INVALID_SOCKET);sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDR);assert(0 == bind(sock,(const sockaddr*)&addr,sizeof(sockaddr_in)));listen(sock,MAX_CONNECT);

    HANDLE hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,NULL);if(hThread == NULL){   assert(0);   closesocket(sock);   WSACleanup();}

    while(1){   sockaddr_in addr;   int   len = sizeof(sockaddr_in);   memset(&addr,0,len);   SOCKET client = accept(sock,(sockaddr*)&addr,&len);

       assert(client != INVALID_SOCKET);

       printf("client[%s] establish connection .../n",inet_ntoa(addr.sin_addr));   printf("client port[%d].../n",ntohs(addr.sin_port));     g_OleData[g_dwNum] = new OlData;   g_OleData[g_dwNum]->wb.len = MSG_SIZE;   g_OleData[g_dwNum]->wb.buf = g_OleData[g_dwNum]->buff;   g_OleData[g_dwNum]->dwFlag = 0;   g_OleData[g_dwNum]->dwRecv = 0;   g_OleData[g_dwNum]->ol.hEvent = g_Event[g_dwNum] = WSACreateEvent();   g_Socket[g_dwNum] = client;   ++g_dwNum;

       WSARecv(client,     &(g_OleData[g_dwNum-1]->wb),     1,     &(g_OleData[g_dwNum-1]->dwRecv),     &(g_OleData[g_dwNum-1]->dwFlag),     &(g_OleData[g_dwNum-1]->ol),     NULL);}

    closesocket(sock);WSACleanup();return 0;}

    DWORD WINAPI ThreadProc(LPVOID lpPara){BOOL ret = FALSE;while(true){   int index = WSAWaitForMultipleEvents(g_dwNum,            (const WSAEVENT*)g_Event,            FALSE,            1000,            FALSE);   if(index == WSA_WAIT_FAILED || index == WSA_WAIT_TIMEOUT)    continue;     index = index - WSA_WAIT_EVENT_0;   ret = WSAGetOverlappedResult(g_Socket[index],           &(g_OleData[index]->ol),           &(g_OleData[index]->dwRecv),           FALSE,           &(g_OleData[index]->dwFlag)           );

       if(ret)   {    if(g_OleData[index]->dwRecv > 0)    {     WSAResetEvent(g_OleData[index]->ol.hEvent); //将其置为无信号状态     g_OleData[index]->buff[g_OleData[index]->dwRecv] = '/0';     printf("recv data:[%s]/n",g_OleData[index]->buff);

         send(g_Socket[index],"Received OK ...",strlen("Received OK ..."),0);     g_OleData[index]->dwFlag = 0;     g_OleData[index]->dwRecv = 0;     memset(g_OleData[index]->buff,0,MSG_SIZE);

         WSARecv(g_Socket[index],       &g_OleData[index]->wb,       1,       &g_OleData[index]->dwRecv,       &g_OleData[index]->dwFlag,       &g_OleData[index]->ol,       NULL);    }    else //当g_OleData[index]->dwRecv == 0,表示该客户端断开连接    {     printf("Client has been disconnect ... /n");     delete g_OleData[index];     g_Event[index] = g_Event[g_dwNum -1];     g_Socket[index] = g_Socket[g_dwNum - 1];     g_OleData[index] = g_OleData[g_dwNum - 1];

         --g_dwNum;    }   }

       else    printf("WSARecv error .../n");}printf("Child thread has been end .../n");return 0;}

    最新回复(0)