文章目录
- Windows网络与通信程序设计实验四:基于WSAEventSelect模型的通信仿真
- 1. WSAEventSelect模型的相关函数:
- 1.1 WSACreateEvent函数
- 1.2 WSAEventSelect函数
- 1.3 WSAWaitForMultipleEvents函数
- 1.4 WSAEnumNetworkEvents函数
- 2. WSAEventSelect模型的相关流程图
Windows网络与通信程序设计实验四:基于WSAEventSelect模型的通信仿真
引子:
WSAEventSelect模型
该模型与WSAAsyncSelect模型类似,允许应用程序在一个或者多个套接字上接收基于事件的网络通知。
不过它并不是依靠Windows的消息驱动机制,
而是经由事件对象句柄通知。
- 当然它与WSAAsyncSelect模型类似,都是接收FD_XXX类型的网络事件。
- 本模型中存在两个需要严格区分的概念:网络事件以及事件对象。
1. WSAEventSelect模型的相关函数:
- 流程概述:
- 使用这个模型的基本思路是为感兴趣的一组网络事件创建一个事件对象,再调用WSAEventSelect函数将网络事件和事件对象关联起来。
- 当网络事件发生时,Winsock使相应的事件对象受信,在事件对象上等待的函数就会返回。
- 之后再调用WSAEnumNetworkEvents函数就可以获知到底发生了什么网络事件。
- 最后便可以根据具体的网络事件类型来对其进行具体处理啦。
1.1 WSACreateEvent函数
- 该函数的定义如下:
WSAEVENT WSACreateEvent (void); //返回一个事件对象的句柄
- 该函数无需传入任何参数,它仅仅是一个很单纯的创建事件对象的WSA函数。
1.2 WSAEventSelect函数
- 该函数的定义如下:
int WSAEventSelect(
SOCKER s, // 套接字句柄
WSAEVENT hEventObject, //事件对象句柄
long lNetworkEvents //感兴趣的网络事件的组合
);
- 该函数可以在网络事件发生的时候,将一组网络事件和创建好的事件对象关联起来。
- 在网络事件和事件对象关联之后,应用程序便可以在事件对象上等待了。
- Winsock提供了WSAWaitForMultipleEvents函数在一个或多个事件对象上等待,当所等待的事件受信或者超过指定的时间时,此函数返回。
1.3 WSAWaitForMultipleEvents函数
- 该函数的定义如下:
DWORD WSAWaitForMultipleEvents(
DWORD cEvents, //指向下面lphEvents所指的数组中事件对象句柄的个数
const WSAEVENT* lphEvents, //指向一个事件对象句柄的数组的指针
BOOL fWaitAll, //指定是否等待所有事件对象都变成受信状态
DWORD dwTimeout, //指定要等待的时间,WSA_INFINITE为无穷大
BOOL fAlertable //在使用WSAEventSelect模型时可以忽略,应设为FALSE
);
- WSAWaitForMultipleEvents函数最多支持WSA_MAXIMUM_WAIT_EVENTS个对象,且WSA_MAXIMUM_WAIT_EVENTS被定义为64。因此这个I/O模型在一个线程中同一时间能最多处理的套接字的个数最多只有64个套接字,如果需要这个模型去管理更多的套接字,就需要创建额外的工作线程了。
- 该函数会等待网络事件的发生。
- 如果过了指定的时间,函数就会返回WSA_WAIT_TIMEOUT;
- 如果在指定的时间内有网络事件发生,函数的返回值就会指明是哪一个事件对象促使函数返回的;
- 如果函数调用失败,那么函数就会返回WSA_WAIT_FAILED.
- 也可以将dwTimeout的值设置为0,这样子,一旦有网络事件发生,函数就会立刻返回,此时可以通过返回值判断事件对象是否受信。
- 若将fWaitAll设置成FALSE后,如果有几个事件对象受信,WSAWaitForMultipleEvents的返回值也依然仅能指明一个,就是句柄数组中最前面的那一个。
- 如果指明的这个事件对象总有网络事件发生,那么后面的其它事件对象所关联的网络事件就得不到处理了。
- 解决办法是,WSAWaitForMultipleEvents函数返回后,对每个事件都再次调用WSAWaitForMultipleEvents函数以便确定其状态。
一旦事件对象受信,那么找到与之对应的套接字,然后调用WSAEnumNetworkEvents函数就可以查看到底发生了什么类型的网络事件。
1.4 WSAEnumNetworkEvents函数
- 该函数的定义如下:
int WSAEnumNetworkEvents(
SOCKETR s, //套接字句柄
WSAEVENT hEventObjecj, //和套接字对应的事件对象句柄
LPWSANETWORKEVENTS lpNetworkEvents //指向一个WSANETWORKEVENTS结构
);
- 如果该函数中指定了hEventObject,则该事件对象的状态会被重置。
- 该函数的最后一个参数用来取得在套接字上发生的网络事件和相关的出错代码。
typedef struct_WSANETWORKEVENTS{
long lNetworkEvents; //指定已经发生的网络事件
int iErrorCode[FD_MAX_EVENTS]; //与lNetworkEvents相关的出错代码
}WSANETWORKEVENTS, *LPWSANETWORKEVENTS;
- 其中iErrorCode是一个数组,数组的每一个成员对应着一个网络事件的出错代码。
- 可以用预定义标识FD_READ_BIT、FD_WRITE_BIT等来索引FD_READ、FD_WRITE等事件发生时的出错代码。