三.Windows I/O模型之事件选择(WSAEventSelect )模型

1.事件选择模型:和异步选择模型类似的是,它也允许应用程序在一个或多个套接字上,接收以事件为基础的网络事件通知。对于异步选择模型采用的网络事件来说,它们均可原封不动地移植到事件选择模型。事件选择模型和异步选择模型最主要的差别在于网络事件会投递至一个事件对象句柄,而非投递至一个窗口例程。
2.创建事件对象:事件选择模型要求应用程序针对打算使用事件选择模型的每一个套接字,首先创建一个事件对象。创建方法是调用WSACreateEvent函数,它的定义如下:WSAEVENT WSACreateEvent(void);
3.绑定事件对象与套接字:
int WSAEventSelect(
    SOCKET s,
    WSAEvent hEventObject,
    long lNetworkEvents//网络事件,就是异步选择中的网络事件,用法完全相同
    );
 对于事件来说,他有两种类型,自动事件和人工事件。有两种状态,未触发状态和触发状态。使用WSACreateEvent函数创建的事件默认为人工事件且处于未触发状态。随着网络事件触发了与一个套接字关联在一起的事件对象,工作状态便会从未触发状态转变成触发状态。由于事件对象是在一种人工重设模式中创建的,所以在完成了一个I/O请求的处理之后,我们的应用程序需要负责将工作
状态触发状态更改未触发状态。
4.重置事件为未触发状态:
BOOL WSAResetEvent(WSAEVENT hEvent);
该函数的功能就是把时间从触发状态重置为未触发状态
5.关闭事件对象,释放其所占用的内核资源:
BOOL WSACloseEvent(WSAEVENT hEvent);
6.监视事件对象的状态:
DWORD WSAWaitForMultipleEvents(
    DWORD cEvents;//事件对象数组中事件的数目
    const WSAEVENT FAR* lphEvents,//事件对象数组
    BOOL fWaitAll,//该参数指明了是否要等到所有事件对象变为触发状态函数才返回
    DWORD dwTimeout,//超时,毫秒为单位超过规定的时间,函数就会立即返回,即使由fWaitAll参数规定的条件尚未满足也如此
    BOOL fAlertable//忽略,置为FALSE
    );
参数:
    要注意的是,WSAWaitForMultipleEvents只能支持由WSA_MAXIMUM_WAIT_EVENTS对象规定的一个最大值,在此定义成6 4个。因此,针对发出WSAWaitForMultipleEvents调用的每个线程,该I/O模型一次最多都只能支持6 4个套接字。假如想让这个模型同时管理不止64个套接字,必须创建额外的工作者线程,以便等待更多的事件对象。fWaitAll 参数指定了指明了是否要等到所有事件对象变为触发状态函数才返回。若设为TRUE,那么只有等lphEvents数组内包含的所有事件对象都已进入触发状态,函数才会返回;但若设为FALSE,任何一个事件对象进入触发状态,函数就会返回。就后一种情况来说,返回值指出了到底是哪个事件对象造成了函数的返回。通常,应用程序应将该参数设为FALSE,通常,dwTimeout被置为0.
一次只为一个套接字事件提供服务    
函数解释:
一个套接字同一个事件对象句柄关联在一起后,应用程序便可开始I/O处理;方法是等待网络事件触发事件对象句柄的工作状态。WSAWaitForMultipleEvents函数的设计宗旨便是用来等待一个或多个事件对象句柄,并在事先指定的一个或所有事件对象进入触发状态后,
或在超过了一个规定的时间周期后,立即返回。
7.确定网络事件发生的套接字:若WSAWaitForMultipleEvents收到一个事件对象的网络事件通知,便会返回一个值,指出造成函数返回的事件对象。这样一来,我们的应用程序便可引用事件数组中已传信的事件,并检索与那个事件对应的套接字,判断到底是在哪个套接字上,发生了什么网络事件类型。对事件数组中的事件进行引用时,应该用WSAWaitForMultipleEvents的返回值,减去预定义值WSA_WAIT_EVENT_0,得到具体的引用值(即索引位置)。
Index=WSAWaitForMultipleEvents(...);
myEvent=EventArray[Index-WSA_WAIT_EVENT_0];
7.调查发生的网络事件类型:
int WSAEnumNetworkEvents(
    SOCKET s,
    WSAEVENT hEventObjects,//参数可选,对应于打算重设的事件对象,即设置事件为未触发状态。和WSAtResetEvent函数功能相同
    LPWSANETWORKEVENTS lpNetworkEvents//用来接受发生的网络事件类型以及可能出现的任何错误代码
    );
该函数中的第四个参数用来接收发生的网络事件类型
8.WSANETWORKEVENTS结构:
tydef struct _WSANETWORKEVENTS
{
    long lNetworkEvents;//网络事件类型
    long iErrorCode[FD_MAX_EVENTS];//错误代码
}WSANETWORKEVENTS,FAR* LPWSANETWORKEVENTS;
iErrorCode参数指定的是一个错误代码数组,同lNetworkEvents中的事件关联在一起。iErrorCode针对每个网络事件类型,都存在着一个特殊的事件索引,名字与事件类型的名字类似,只是要在事件名字后面添加一个“ _BIT”后缀字串即可.

示例代码:

 1 SOCKET Socket[WSA_MAXIMUM_WAIT_EVENTS];//64
 2 WSAEVENT event[WSA_MAXIMUM_WAIT_EVENTS];
 3 SOCKET accept,listen;
 4 DWORD eventTotal=0;
 5 DWORD index;
 6
 7 //创建套接字
 8 listen=socket(...);
 9
10 //绑定本地地址
11 bind(...);
12
13 //创建事件对象
14 WSAEVENT newEvent;
15 newEvent=WSACreateEvent();
16
17 //注册网络事件
18 WSAEventSelect(listen,newEvent,FD_ACCEPT|FD_CLOSE);
19
20 Socket[eventTotal]=listen;
21 event[eventTotal]=newEventl;
22 eventTotal++;
23
24
25 while(1)
26 {
27     //等待事件触发状态
28     index=WSAWaitForMultipleEvents(eventTotal,event,FALSE,WSA_INFINITE,FALSE);
29
30     //查看发生的网络事件类型,确定发生网络事件的套接字
31     WSANETWORKEVENTS networkEvents;
32     WSAEnumNetworkEvents(Socket[index-WSA_WAIT_EVENT_0],event[index-WSA_WAIT_EVENT_0],&networkEvents);
33
34     //确定发生的网络事件类型
35     if(networkEvents.lNetworkEvents&FD_ACCEPT)
36     {
37         if(networkEvents.iErrorCode[FD_ACCEPT_BIT]!=0)
38         {
39             printf("FD_ACCEPT failed with error %d\n",networkEvents.iErrorCode[FD_ACCEPT_BIT]);
40             break;
41         }
42
43         //FD_ACCEPT事件发生后,则进行后续处理
44         accept=accept(Socket[index_WSA_WAIT_EVENT_0],NULL,NULL);
45
46         //查看事件对象的数目
47         if(eventTotal>WSA_MAXIMUM_WAIT_EVENTS)
48         {
49             printf("too many connections\n");
50             closesocket(accept);
51             break;
52         }
53
54         //再次创建事件,再次进行上述操作,进行循环
55         newEvent=WSACreateEvent();
56
57         WSAEventSelect(listen, newEvent, FD_READ|FD_WRITE | FD_CLOSE);
58
59         event[eventTotal]=newEvent;
60         Socket[eventTotal]=accept;
61         eventTotal++;
62         printf("socket %d connected\n",accept);
63     }
64
65     //FD_READ事件的处理
66     //雷同于FD_ACCEPT网络事件的处理
67     if(networkEvents.lNetworkEvents&FD_READ)
68     {
69         if(networkEvents.iErrorCode[FD_READ_BIT]!=0)
70         {
71             printf("FD_READ failed with error %d\n",networkEvents.iErrorCode[FD_READ_BIT]);
72             break;
73         }
74         //读取数据
75         recv(Socket[index-WSA_WAIT_EVENT_0],buf,sizeof(buf),0);
76     }
77
78     //接下来其他网络事件的处理同上,但是需要注意一点,事件选择模型是基于窗口程序的,并且需要消息发送,只是这部分代码为给出而已
79
80 }
81
82
83
84     

时间: 2024-08-01 09:38:04

三.Windows I/O模型之事件选择(WSAEventSelect )模型的相关文章

一.Windows I/O模型之选择(select)模型

1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作.避免套接字进入阻塞模式,进行无谓的等待.选择模型的核心的FD_SET集合和select函数.通过该函数,我们可以们判断套接字上是否存在数据,或者能否向一个套接字写入数据. 2.select函数:int select(    int nfds,//忽略,只是为了兼容而存在.    fd_set FAR* readfds,//可读性检查(有数据可读入,连接关闭,重设,终止) 

JavaScript事件模型及事件代理

事件模型 JavaScript事件使得网页具备互动和交互性,我们应该对其深入了解以便开发工作,在各式各样的浏览器中,JavaScript事件模型主要分为3种:原始事件模型.DOM2事件模型.IE事件模型. 1.原始事件模型(DOM0级) 这是一种被所有浏览器都支持的事件模型,对于原始事件而言,没有事件流,事件一旦发生将马上进行处理,有两种方式可以实现原始事件: (1)在html代码中直接指定属性值:<button id="demo" type="button"

Windows下Qt开发环境:OpenGL导入3DMax模型(.3DS)

参考:http://blog.csdn.net/cq361106306/article/details/41876541 效果: 源代码: 解释: CLoad3DS.h为加载3DMax模型的头文件,CLoad3DS.cpp为加载3DMax模型的实现文件, nehewidget.h为Qt下使用OpenGL头文件,nehewidget.cpp为Qt下使用OpenGL实现文件. 注意: 1.3D模型和纹理图片资源需要放在源代码同一目录下的Data目录中,即/Data/3DS和/Data/pic下. 2

整理之DOM事件阶段、冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件

整理之DOM事件阶段 本文主要解决的问题: 事件流 DOM事件流的三个阶段 先理解流的概念 在现今的JavaScript中随处可见.比如说React中的单向数据流,Node中的流,又或是今天本文所讲的DOM事件流.都是流的一种生动体现.用术语说流是对输入输出设备的抽象.以程序的角度说,流是具有方向的数据. 事件流分事件冒泡与事件捕获 在浏览器发展的过程中,开发团队遇到了一个问题.那就是页面中的哪一部分拥有特定的事件? 可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其

字典转模型(国旗选择)

"[案例: 国旗选择]" //此处插入国旗选择的图片 >加载flags.plist数据到 "国旗模型[Flag.h]" >掌握代理[-(UIView *)pickerView:viewForRow:forComponent:reusingView:]的使用 (1)在数据源里返回一组数据,行数由国旗个数决定 (2)在代理方法中使用上面的方法,每一行返回一个View,返回的这个view为label (3)打印reusingView的地址和文字,"查

【scikit-learn】如何进行模型参数的选择

内容概要 这一节我们介绍以下几个内容: 我们该怎样选择模型用于监督学习任务? 我们该如何选择调整得到最好的模型参数? 我们该如何对测试数据进行预测估计? 1. 使用整个数据集进行训练和测试 这里我们使用手中的整个数据集来训练模型 使用同样的数据集来测试模型,然后评估预测的结果和真实结果的差别 In [1]: from sklearn.datasets import load_iris iris = load_iris() # create X(features) and y(response)

背水一战 Windows 10 (32) - 控件(选择类): Selector, ComboBox

原文:背水一战 Windows 10 (32) - 控件(选择类): Selector, ComboBox [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(选择类) Selector ComboBox 示例1.Selector(基类) 的示例Controls/SelectionControl/SelectorDemo.xaml <Page x:Class="Windows10.Controls.SelectionControl.SelectorDemo&q

背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch

原文:背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(选择类) ListBox RadioButton CheckBox ToggleSwitch 示例1.ListBox 的示例Controls/SelectionControl/ListBoxDemo.xaml <Page x:Class="Window

机器学习笔记(二)模型评估与选择

2.模型评估与选择 2.1经验误差和过拟合 不同学习算法及其不同参数产生的不同模型,涉及到模型选择的问题,关系到两个指标性,就是经验误差和过拟合. 1)经验误差 错误率(errorrate):分类错误的样本数占样本总数的比例.如果在m个样本中有a个样本分类错误,则错误率E=a/m,相应的,1-a/m称为精度(accuracy),即精度=1-错误率. 误差(error):学习器的实际预测输出和样本的真实输出之间的差异.训练误差或经验误差:学习器在训练集上的误差:泛化误差:学习器在新样本上的误差.