select使用
select函数介绍
int select(int maxfd,fd_set *readset,fd_set *writeset, fd_set *exceptset,const struct timeval *timeout)
- maxfd:监视对象文件描述符数量
- readset:将所有关注’是否存在待读数据‘的文件描述符注册到fd_set型变量,并传递地址
- writeset:将所有关注’是否存在待读数据‘的文件描述符注册到fd_set型变量,并传递地址
- exceptset:将所有关注’是否发生异常’的文件描述符注册到fd_set型变量,并传递地址
- timeout:定时器,防止陷入无限阻塞的状态,用来传递超时信息
- 返回值:错误时返回-1,超时返回0,返回值大于0时,表示发生事件的文件描述符数
那么fd_set是什么呢? fd_set是位图,位图是一连串的bit,只有0和1的状态。
可以把它理解成一个bool数组,只有两个状态true和false,true表示已注册事件或发生了事件,false表示相反的意思。
FD_ZERO(int fd,fd_set *fdset):将所有fd_set变量的所有位初始化为0 FD_SET(int fd,fd_set *fdset):在参数fdset指向的变量中注册文件描述符fd(对应位置赋值为1) FD_CLR(int fd,fd_set *fdset):从参数fdset指向的变量中清楚文件描述符fd(对应位置赋值为0) FD_ISSET(int fd,fd_set *fdset):若参数fdset指向的变量包含文件描述符fd的信息,则返回true
使用例子:
#include<stdio.h>
#include<unistd.h>
#include<sys/time.h>
#include<sys/select.h>
int main()
{
fd_set reads,cpy_reads;
struct timeval timeout;
int num,i;
FD_ZERO(reads);
FD_SET(0,&reads);
/*
定时器数据结构:
struct timeval{
long tv_sec;
long tv_usec;
}
*/
//设置定时5秒
timeout.tv_sec = 5;
timeout.tv_usec = 0;
while(1) {
cpy_reads = reads;//由于每次都会刷新cpy_reads,所以需要循环初始化
num = select(3 + 1,&cpy_reads,0,0,&timeout);//关于第一个参数:在linux中,文件描述符0,1,2分别表示标准输入、标准输出、错误。若在服务器程序中,一般第一个参数填守候socket
for(i = 0; i < 4; i++) {
if(FD_ISSET(i,&cpy_reads)) {
//此文件描述符i有数据可读
...
}
}
}
}