select模型
select(选择)模型是Winsock中最常见的I/O模型.之所以称其为"select模型",是由于它的"中心思想"便是利用select函数,实现对I/O的管理!最初设计该模型时,主要面向的是某些使用Unix操作系统的计算机,它们采用的是Berkeley套接字方案.select 模型已集成到Winsock 1.1中,它使那些想避免在套接字调用过程中被无辜"锁定"的应用程序,采用一种
有序的方式,同时进行对多个套接字的管理.由于Winsock 1.1向后兼容于Berkeley套接字实施方案,所以假如有一个Berkeley套接字应用使用了select函数,那么从理论角度讲,务须对其进行任何修改,便可正常运行.
利用select函数,我们判断套接字上是否存在数据,或者能否向一个套接字写入数据.之所以要设计这个函数,唯一的目的便是防止应用程序在套接字处于锁定模式中时,在一次I/O绑定调用(如send 或recv)过程中,被迫进入"锁定"状态;同时防止在套接字处于非锁定模式中时,产生WSAEWOULDBLOCK错误.除非满足事先用参数规定的条件,否则select函数会在进行I/O操作时锁定. select的函数原型如下:
int select(
int nfds,
fd_set FAR* readfds,
fd_set FAR* writefds,
fd_set FAR* exceptfds,
const struct timeval FAR* timeout
);
其中,第一个参数nfds会被忽略.之所以仍然要提供这个参数,只是为了保持与早期的Berkeley套接字应用程序的兼容.大家可注意到三个 fd_set参数:一个用于检查可读性(readfds),一个用于检查可写性(writefds),另一个用于例外数据(exceptfds).从根本上说,fd_set数据类型代表着一系列特定套接字的集合.其中,readfds集合包括符合下述任何一个条件的套接字:
有数据可以读入.
连接已经关闭、重设或中止.
假如已调用了listen,而且一个连接正在建立,那么accept函数调用会成功。
writefds集合包括符合下述任何一个条件的套接字:
有数据可以发出.
如果已完成了对一个非锁定连接调用的处理,连接就会成功.
最后,exceptfds集合包括符合下述任何一个条件的套接字:
假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败.
有带外(Out-of-band,OOB)数据可供读取.