-
Windows下类似与Linux下的
epoll
异步通知IO模型(不是异步IO模型)是基于WSAEventSelect
实现的(还有一种WSAAsyncSelect
也能实现,不过一般用于UI); -
WSAEventSelect
实现的异步通知IO模型的过程:- 使用
WSACreateEvent()
创建一个手动重置事件(注意结束时要用WSACloseEvent()
来销毁这个手动重置事件); - 使用
WSAEventSelect()
将一个句柄(比如socket句柄)与上一步创建的手动重置事件进行绑定,调用此函数时第三个参数传入事件类型,表示当对应的句柄发生此类型的事件的时候,就将手动重置事件变成signaled状态(激发态)。注意,这个函数每次调用只能将一个句柄与一个手动重置事件进行绑定,类似与epoll中的epoll_ctl()
每次只能注册一个; - 调用
WSAWaitForMultipleEvents()
来等待一组事件的发生。一组事件是通过数组传入的,可以选择等待任意一个事件发生就返回,也可以选择等待所有事件都发生了才返回,因此,这是一个阻塞函数,类似与epoll中的epoll_wait()
。不过,注意,等待的最大事件个数一般为64个,可以通过宏WSA_MAXIMUM_WAIT_EVENTS
来获取最大可等待事件个数; - 上一步只能得到所有被激发事件中的第一个被激发事件的数组下标(通过返回值获得),如果想得到所有被激发的事件,则要循环调用
WSAWaitForMultipleEvents()
,比如:
注意,后面循环里面不再是无限等待,而是不等待,只是为了拿到已经激发的事件的下标;int posInfo = WSAWaitForMultipleEvents(numOfSock, hEventArray, FALSE, WSA_INFINITE, FALSE); int startIdx = posInfo - WSA_WAIT_EVENT_0; ..... for (int i = startIdx; i < numOfSock; ++i) { int sigEventIdx = WSAWaitForMultipleEvents(1, &hEventArray[i], TRUE, 0, FALSE); ...... }
- 通过函数
WSAEnumNetWorkEvents()
来区分事件的类型。此函数需要传入一个socket句柄,以及之前通过WSAEventSelect()
进行绑定的手动重置事件的句柄,并传入一个WSANETWORKEVENTS
结构体指针,用来返回事件的类型以及出错类型; - 通过检测事件类型来得到当前socket句柄发生了什么事件,从而决定做什么事情。
- 使用
-
注意,如果要删除事件数组中的一个事件,必须将数组压缩,中间不能空,要将后面的事件前移一个位置;
-
事件的类型有如下几种:
FD_READ:是否存在需要接收的数据; FD_WRITE:能否以非阻塞方式传输数据(意思应该是输出缓冲区是否可以填充数据,而不需要等待); FD_OOB:是否收到带外数据; FD_ACCEPT:是否有新的连接请求; FD_CLOSE:是否有断开连接的请求(应该是对法发送了EOF吧)。
TCP/IP网络编程学习笔记(十一)
最新推荐文章于 2024-04-16 18:03:36 发布