WSAEventSelect-事件通知模型

该模型最主要的差别在于网络事件会投递至一个事件对象句柄,而非投递至一个窗口例程。

事件通知
事件通知模型要求我们的应用程序针对打算使用的每一个套接字,首先创建一个事件对象。创建方法是调用W S A C r e a t e E v e n t函数,它的定义如下:
WSAEVENT WSACreateEvent(void);

 

WSAWaitForMultipleEvents

若W S AWa i t F o r M u l t i p l e E v e n t s收到一个事件对象的网络事件通知,便会返回一个值,指出造成函数返回的事件对象。这样一来,我们的应用程序便可引用事件数组中已传信的事件,并检索与那个事件对应的套接字,判断到底是在哪个套接字上,发生了什么网络事件类型。对事件数组中的事件进行引用时,应该用 W S AWa i t F o r M u l t i p l e E v e n t s的返回值,减去预定义
值W S A _ WA I T _ E V E N T _ 0,得到具体的引用值(即索引位置)。如下例所示:
Index = WSAWaitForMultipleEvents(...);
MyEvent = EventArray[Index-WSA_WAIT_EVENT_0];

 

 

 

 

 

 

 

 

 

  1. #include <stdio.h> 
  2. #include <iostream.h> 
  3. #include <windows.h> 
  4. // 初始化Winsock库 
  5. BOOL InitWinsock() 
  6.    // 初始化Winsock库 
  7. int main() 
  8.     InitWinsock(); 
  9.    // 事件句柄和套节字句柄表 
  10.     WSAEVENT    eventArray[WSA_MAXIMUM_WAIT_EVENTS]; 
  11.     SOCKET        sockArray[WSA_MAXIMUM_WAIT_EVENTS]; 
  12.     int nEventTotal = 0; 
  13.     USHORT nPort = 4567;    // 此服务器监听的端口号 
  14.     // 创建监听套节字 
  15.     SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);     
  16.     sockaddr_in sin; 
  17.     sin.sin_family = AF_INET; 
  18.     sin.sin_port = htons(nPort); 
  19.     sin.sin_addr.S_un.S_addr = INADDR_ANY; 
  20.     if(::bind(sListen, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) 
  21.     { 
  22.         printf(" Failed bind() /n"); 
  23.         return -1; 
  24.     } 
  25.     ::listen(sListen, 5); 
  26.    // 创建事件对象,并关联到新的套节字 
  27.     WSAEVENT event = ::WSACreateEvent(); 
  28.     ::WSAEventSelect(sListen, event, FD_ACCEPT|FD_CLOSE); 
  29.     // 添加到表中 
  30.     eventArray[nEventTotal] = event; 
  31.     sockArray[nEventTotal] = sListen;     
  32.     nEventTotal++; 
  33.     // 处理网络事件 
  34.     while(TRUE) 
  35.     { 
  36.         // 在所有事件对象上等待 
  37.         int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE); 
  38.         // 对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态 
  39.         nIndex = nIndex - WSA_WAIT_EVENT_0; 
  40.         for(int i=nIndex; i<nEventTotal; i++) 
  41.         { 
  42.             nIndex = ::WSAWaitForMultipleEvents(1, &eventArray, TRUE, 1000, FALSE); 
  43.             if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT) 
  44.             { 
  45.                 continue
  46.             } 
  47.             else 
  48.             { 
  49.                 // 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件 
  50.                 WSANETWORKEVENTS event; 
  51.                 ::WSAEnumNetworkEvents(sockArray, eventArray, &event); 
  52.                 if(event.lNetworkEvents & FD_ACCEPT)               // 处理FD_ACCEPT通知消息 
  53.                 { 
  54.                     if(event.iErrorCode[FD_ACCEPT_BIT] == 0) 
  55.                     { 
  56.                         if(nEventTotal > WSA_MAXIMUM_WAIT_EVENTS) 
  57.                         { 
  58.                             printf(" Too many connections! /n"); 
  59.                             continue
  60.                         } 
  61.                         SOCKET sNew = ::accept(sockArray, NULL, NULL); 
  62.                         WSAEVENT event = ::WSACreateEvent(); 
  63.                         ::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE); 
  64.                         // 添加到表中 
  65.                         eventArray[nEventTotal] = event; 
  66.                         sockArray[nEventTotal] = sNew;     
  67.                         nEventTotal++; 
  68.                     } 
  69.                 } 
  70.                 else if(event.lNetworkEvents & FD_READ)            // 处理FD_READ通知消息 
  71.                 { 
  72.                     if(event.iErrorCode[FD_READ_BIT] == 0) 
  73.                     { 
  74.                         char szText[256]; 
  75.                         int nRecv = ::recv(sockArray, szText, strlen(szText), 0); 
  76.                         if(nRecv > 0)                 
  77.                         { 
  78.                             szText[nRecv] = '/0'
  79.                             printf("接收到数据:%s /n", szText); 
  80.                         } 
  81.                     } 
  82.                 } 
  83.                 else if(event.lNetworkEvents & FD_CLOSE)        // 处理FD_CLOSE通知消息 
  84.                 { 
  85.                     if(event.iErrorCode[FD_CLOSE_BIT] == 0) 
  86.                     { 
  87.                         ::closesocket(sockArray); 
  88.                         for(int j=i; j<nEventTotal-1; j++) 
  89.                         { 
  90.                             sockArray[j] = sockArray[j+1]; 
  91.                             sockArray[j] = sockArray[j+1];     
  92.                         } 
  93.                         nEventTotal--; 
  94.                     } 
  95.                 } 
  96.                 else if(event.lNetworkEvents & FD_WRITE)        // 处理FD_WRITE通知消息 
  97.                 { 
  98.                 } 
  99.             } 
  100.         } 
  101.     } 
  102.     return 0; 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值