一、select函数说明
int select(int maxfd, fd_set *readset,fd_set *writeset, fd_set *exceptset,const struct timeval *timeout);
功能:指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或经历一段指定时间后才唤醒参数:
maxfd:这是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1
readset:可读描述符集,指向fd_set结构的指针,监测该集合中的任意描述符是否有数据可读,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。
writeset:可写描述符集,监测该集合中的任意描述符是否有数据可写,同上
exceptset:异常描述符集,监测该集合中的任意描述符是否发生异常,同上
timeout:超时时间,具体有三种情况,第一:若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二:若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三:timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
返回值:0 => 超时,-1 => 出错:正数(>0) => 准备好的描述符数量
头文件:#include <sys/select.h>,#incldue <sys/time.h>
二、补充说明两个结构体:
<1> struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以,毫无疑问,一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来操作,比如清空集合:FD_ZERO(fd_set*)、加入集合之中:FD_SET(int, fd_set*)、从集合中删除:FD_CLR(int, fd_set*)、检查集合:FD_ISSET(int, fd_set*)。
<2> struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个毫秒数。
struct timeval
{
long tv_sec; //秒
long tv_usec; //微秒
};
三、与select函数相关的几个宏
FD_ZERO(fd_set *fdset):初始化清空fdset文件描述符集
FD_SET(int fd, fd_set *fdset):将文件描述符fd加入fdset文件描述符集
FD_CLR(int fd, fd_set *fdset):将文件描述符fd从fdset文件描述符集中删除
FD_ISSET(int fd, fd_set *fdset):监测fd文件描述符是否有事件发生(具体是什么事件得看实际编程情况)