重叠IO之事件通知模型

/**********************************************************************
*   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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值