事件选择(WSAEventSelect)模型:基于事件通知,事件是一个有操作系统管理的内核对象,当前系统基于事件机制,该模型则可以使用,事件两种状态,有信号和无信号,检测事件,若有信号则进行相应处理。
参考博客:http://www.cnblogs.com/venow/archive/2012/06/12/2543065.html
优点:(1)可以在非窗口的Windows Socket程序中,实现多个套接字的管理。
缺点:(1)不能同时处理多个Socket,有数量限制。要么Wait一个事件对应一个线程,(2)仍然属于阻塞模型,异步阻塞模型。(3)每个WSAEventSelect模型最多只能管理64个套接字。当应用程序中要管理多余64个套接字时,就需要额外创建线程。
3.1、创建一个无信号的事件 WSAEVENT------HANDLE
WSAEVENT we=WSACreateEvent();
3.2、向Windows注册网络事件。
int WSAEventSelect(
_In_ SOCKET s, //监控的网络事件
_In_ WSAEVENT hEventObject, // 创建的事件
_In_ long lNetworkEvents //网络事件类型
);
//注册完的事件加入到监测的事件数组,将socket加入到对应的socket数组。
3.3、创建线程---看事件是否有信号,
m_hthread = (HANDLE) _beginthread(NULL,0,&threadRecv,this,0,NULL);
DWORD WINAPI threadRecv( LPVOID lpvoid) //线程的入口函数
{
UDPNet * pthis = (UDPNet *)lpvoid;
char szBuf[_DEFAULT_PACK] = {0};
Sockaddr_in addrClient;
Int nSize = sizeof(sockaddr_in);
While(pthis->m_bFlag)
{
WSAWaitForMultipleEvents(...);
}
return 0;
}
3.4、查看是否有事件发生
DWORD WSAWaitForMultipleEvents(
DWORD cEvents, // 等候事件的总数量,数组长度
const WSAEVENT* lphEvents, // 事件数组的指针
BOOL fWaitAll,// 若为TRUE,需所有事件发生才会返回
DWORD dwTimeout, // 超时时间,
BOOL fAlertable//指定线程是否为alertable等待态);
参数介绍:
BOOL fWaitAll, // 这个要多说两句: // 如果设置为TRUE,则事件数组中所有事件被传信的时候函数才会返回 // FALSE则任何一个事件被传信函数都要返回 //如果为FALSE,返回值减去WSA_WAIT_EVENT_0,为当前事件在数组中的索引。只能返回一个
DWORD dwTimeout, // 超时时间,如果超时,函数会返回 WSA_WAIT_TIMEOUT//如果设置为0,函数会立即返回 //如果设置为WSA_INFINITE只有在某一个事件被传信后才会返回, //则WSAWaitForMultipleEvents永远等待,不会出现超时现象。
BOOL fAlertable fAlertable参数,在我们使用 WSAEventSelect模型的时候,它是可以忽略的,且应设为 FALSE。该参数主要用于在重叠式I/O 模型中,在完成例程的处理过程中
3.5、 发生事件的网络事件类型--判断当前发生什么网络事件
int WSAEnumNetworkEvents(
_In_ SOCKET s, //哪个socket
_In_ WSAEVENT hEventObject, //发生什么事件
_Out_ LPWSANETWORKEVENTS lpNetworkEvents //获得发生的网络事件类型
);
//返回值为0,则成功,
typedef struct _WSANETWORKEVENTS{
long lNetworkEvents; //网络事件,如FD_READ 、FD_WRITE
int iErrorCode[FD_MAX_EVENTS];
} WSANETWORKEVENTS, *LPWSANETWORKEVENTS;