2024年3月27日发(作者:)

fd_set参数:一个用于检查可读性(readfds),一个用于检查可写性(writefds),另一个用于例

外数据(exceptfds)。从根本上说,

fd_set数据类型代表着一系列特定套接字的集合。其中,readfds集合包括符合下述任何一个条件的

套接字:

有数据可以读入。

连接已经关闭、重设或中止。

假如已调用了listen,而且一个连接正在建立,那么accept函数调用会成功。

writefds集合包括符合下述任何一个条件的套接字:

有数据可以发出。

如果已完成了对一个非锁定连接调用的处理,连接就会成功。

最后,exceptfds集合包括符合下述任何一个条件的套接字:

假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败。

有带外(Out-of-band,OOB)数据可供读取。

用select对套接字进行监视之前,在自己的应用程序中,必须将套接字句柄分配给一个集

合,设置好一个或全部读、写以及例外fd_set结构。将一个套接字分配给任何一个集合后,再

来调用select,便可知道一个套接字上是否正在发生上述的I/O活动。Winsock提供了下列宏操作,

可用来针对I/O活动,对fd_set进行处理与检查:

FD_CLR(s,*set):从set中删除套接字s。

FD_ISSET(s,*set):检查s是否set集合的一名成员;如答案是肯定的是,则返回TRUE。

FD_SET(s,*set):将套接字s加入集合set。

FD_ZERO(*set):将set初始化成空集合。

例如,假定我们想知道是否可从一个套接字中安全地读取数据,同时不会陷于无休止的

“锁定”状态,便可使用FD_SET宏,将自己的套接字分配给fd_read集合,再来调用select。要

想检测自己的套接字是否仍属fd_read集合的一部分,可使用FD_ISSET宏。采用下述步骤,便

可完成用select操作一个或多个套接字句柄的全过程:

1)使用FD_ZERO宏,初始化自己感兴趣的每一个fd_set。

2)使用FD_SET宏,将套接字句柄分配给自己感兴趣的每个fd_set。

3)调用select函数,I/O活动设置好一个或多个套接字句柄。

然后等待在指定的fd_set集合中,

select完成后,会返回在所有fd_set集合中设置的套接字句柄总数,并对每个集合进行相应的更新。

4)根据select我们的应用程序便可判断出哪些套接字存在着尚未完成(待决)

的返回值,

的I/O操作—具体的方法是使用FD_ISSET宏,对每个fd_set集合进行检查。

5)知道了每个集合中“待决”的I/O操作之后,对I/O进行处理,然后返回步骤1),继续进

行select处理。

select返回后,删除那些不存在待决I/O操作的套接字句柄。

它会修改每个fd_set结构,

若WSAWaitForMultipleEvents收到一个事件对象的网络事件通知,便会返回一个值,指

出造成函数返回的事件对象。这样一来,我们的应用程序便可引用事件数组中已传信的事件,

并检索与那个事件对应的套接字,判断到底是在哪个套接字上,发生了什么网络事件类型。

对事件数组中的事件进行引用时,应该用WSAWaitForMultipleEvents的返回值,减去预定义

值WSA_WAIT_EVENT_0,得到具体的引用值(即索引位置)。如下例所示:

知道了造成网络事件的套接字后,接下来可调用WSAEnumNetworkEvents函数,调查发