WSAEventSelect

WSAEventSelect 模型

  • Winsock提供了另一种有用的异步事件通知I/O模型-WSAEventSelect模型,这个模型与WSAAsyncSelect模型类似,允许应用程序在一个或者多个套接字上接收基于事件的网络通知。它与WSAAsyncSelect模型类似是因为他也接收FD_XXX类型的网络事件,不过并不是靠windows消息驱动机制,而是经过事件对象句柄通知
  • WSAEventSelect 函数
    • 使用这个模型的基本思路是为感兴趣的一组网络事件创建一个事件对象,在调用WSAEventSelect函数将网络事件和事件对象关联起来,当网络发生时,Winsock使相应的事件受信,在事件对象上等待的函数就会返回。然后调用WSAEnumNetworkEvents函数便可获取到底发生了什么网络事件。
  • winsock中创建事件对象的函数使WSACreateEvent,定义如下:
WSAEVENT WSACreateEvent(void);//返回一个手工重置的事件对象句柄
  • 创建事件对象之后,必须调用WSAEvebtSelect函数将指定的一组网络事件与它关联在一起,函数用法如下:
int WSAEventSelect(
SOCKET S,//套接字句柄
WSAEVENT hEventObject,//事件对象句柄
long InetworkEvents//感兴趣的FD_XXX网络事件的组合
)
  • 网络对象与事件对象相关联之后,应用程序便可以在事件对象上等待了。Winsock提供了WSAWaitForMultForMultipleEvents函数在一个或者多个事件对象上等待,当所等待的事件对象受信,或者指定时间过去,此函数返回,函数用法如下:
DWORD WSAWaitForMultipleEvents(
DWORD cEvents,//指定下面lphEvents所指数组中时间对象句柄的个数
const WSAEVENT *lphEvents,//指向一个事件对象句柄数组
BOOL fWaitAll,//指定是否等待所有的事件对象都变成受信状态
DWORD dwTimeout,//指定要等待的时间,WSA_INFINITE为无穷大
BOOL fAlertable //在使用WSAEventSelect模型时可以忽略,应设置为FALSE
)
  • WSAWaitForMultipleEvents最多支持WSA_MAXIMUM_WAIT_EVENTS个对象,MSA_MAXIMUM_WAIT_EVENTS被定义为64,因此这个IO模型在同一时间最多支持64个套接字,如果需要使用这个模型管理更多套接字,需要创建额外的工作线程。
  • WSAWaitForMultipeEvents函数会等待网络事件的发生,如果过了指定的时间,函数返回WSA_WAIT_TIMEOUT,如果在指定时间内有网络事件发生,函数返回值会指明使哪个事件促使函数返回的:函数调用失败时返回值使WSA_WAIT_FAILED
  • 也可以将dwTimeout的值设置为0,这时候函数测试指定事件对象的状态,并立即返回,通过函数的返回值便可知道,函数是否受信。
  • 注意:fWaitAll参数设置为FALSE,如果同时又几个事件对象受信,WSAWaitForMultipleEvents函数的返回值也仅能指明一个,就是句柄数组最前面那一个,如果指明的事件对象总有总有网络事件发生,那么后面的事件对象所关联的网络事件就得不到处理
  • 解决办法:WSAWaitForMultipleEvents函数返回后,对每个事件都再次调用SAEnumNetworkEvents函数以便确定其状态

函数用法

int WSAEnumNetworkEvents(
SOCKET S,//套接字句柄
WSAEVENT hEventObject,//对应的事件句柄对象,如果提供了此函数,本函数会重置这个事件对象的状态
LPWSANETWORKEVENTS lpNetworkEvents//指向WSANETWORKEVENTS结构
)
  • 最后一个参数用来取得在套接字上发生的网络事件和相关的出错代码,其结构定义如下:
typedef struct WSANETWORKEVENTS{
long lNetworkEvents;//指已经发生的网络事件
int iErrorCode[FD_MAX_EVENTS];//与lNetworkEvents相关出错代码
}WSANETWORKEVENTS,*LPWSANETWORKEVENTS;
  • iError参数使一个数组,数组的每个成员对应一个网络事件的出错代码,可以预定义标识FD_READ_BIT、FD_WRITE_BIT等来索引FD_READ等事件发生时的出错代码
if (event.lNetworkEvents &FD_READ)//处理FD_READ通知消息
{
if(event.iErrorCode[FD_READ_BIT]!=0){
..........//FD_READ出错,错误代码为event.iErrorCode[FD_READ_BIT]
}
}
posted @ 2020-08-11 20:08  一生热爱  阅读(459)  评论(0编辑  收藏  举报