现在的位置: 首页 > 综合 > 正文

重叠IO之事件通知模型

2012年10月23日 ⁄ 综合 ⁄ 共 3637字 ⁄ 字号 评论关闭

/**********************************************************************
*   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;
}

抱歉!评论已关闭.