函数原型:
int select(int maxfd,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct
timeval *timeout);
参数一:当前进程的最大文件描述符个数(这里可以以这样理解)
参数二:读可行性集合(若在该集合中表示可读)
参数三:写可行性集合(若在该集合中表示可写)
参数四:异常集合(若产生异常)------该参数我没有深入理解;自己可以查阅相关手册
参数五:用于设置select为阻塞或是非阻塞
参数五解析:设置阻塞或是非阻塞:当此参数为NULL时表示为阻塞;当为0(timeout指向的内存
中的值)根本不等待立即返回;当为非0(同上一行)设定select检测的等待时间。
阻塞:NULL
当第五个参数设定为NULL时,那我们在检测的描述字,必须要有可读,或可写,或错误异常,才
会返回值
应用:
对于在server中的I/O多路复用,我们用select检测套接字等待某个事件发生,或是新客服连接或
是数据、PIN、RST到达
重点理解:
(这里可能和我们之前理解的accept()来记录连接套接字有区别,但实际上是一样的,我们要肯
定一点:实际上客户端请求server连接时和accept无关,accept()不过是来记录这个连接的套接
字,因而在accept前便可检测客服端是否发送来连接请求信息)
非阻塞:timeout设定
struct timeval time1 = {
.tv_sec = 0,
.tv_usec = 0,
};
struct timeval time2 = {
.tv_sec = 3,
.tv_usec = 0,
};
用到time1表示select根本不等待就立即返回0,处理下面的数据(比如打印等:)
用到time2 表示select会等待3秒,如果在限定的时间内没有检测到事件的发生(某个事件,或是
新客服端连接,或是数据到达),就返回0;
FD_ZERO(fdset); 将fdset的所有位清零
FD_SET(fd,fdset); 向fdset中添加fd(turn on the bit for fd in fdset t改变fdset
中的位)
FD_CLR(fd,fdset); 从fdset集合中删除fd,关闭fd在fdset中对应的位
FD_ISSET(fd,fdset); 判断fd是否是在fdset中(这里我要在下面详细说明一下这个用法)
fd_set readfd; 用于可读性检查的集合
应用:套接字的判定
FD_ISSET(s,readfd) ;判断套接字是否可读(这里在该集合中(表示连接请求,或者数据到达)
)) 为非0;否则为0;
这回在我的select阻塞版的server中体现出来,请仔细分析: