现在的位置: 首页 > 综合 > 正文

unp笔记四 select和poll

2017年10月28日 ⁄ 综合 ⁄ 共 1295字 ⁄ 字号 评论关闭

select函数原型

#include<sys/select.h>
#include<sys/time.h>
int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)
返回:若有描述符就绪则为其数目;若超时后,还没有就绪描述符,则为0;出错,则为-1

timeout 等待的时间

struct timeval{
long tv_sec;
long tv_usec;
}
永远等待
等待指定时间
不等待,立即返回
说到等待,那么select有可能:在等待期间,被信号中断,然后从信号处理函数返回,这时就是出错了select返回-1,并置errno为EINTR
当然我们可以设置select自动重启

readset writeset exceptset 指定我们让内核测试的读、写、异常条件的描述符

fd_set readset;//自动变量分配的描述符一定要初始化!!!
FD_ZERO(&readset);
FD_SET(1,&readset);
FD_SET(I,&readset);
select返回后 FD_ISSET(1,&readset);

maxfdp1 待测试的最大描述符加1

这个参数一直让人很奇怪,Stevens说存在这个参数是为了效率,通过它在内核与进程之间可以不复制一些不必要的描述符。

使用select实现简单并发服务器

服务器只维护一个读描述符集
准备一个整型数组,该数组存放连接套接字
int client[FD_SETSIZE]=-1;
fd_set allset;
FD_ZERO(&sllset);
FD_SET(listenfd,&allset);  //listenfd监听套接字总是放在描述符集中
for(;;){
rset=allset;
select(maxfd+1,&rset,NULL,NULL,NULL);
//一旦select返回,先看看listenfd监听套接字是否有新连接来
if(FD_ISSET(listenfd,&rset)){
connfd=accept...
FD_SET(connfd,&rset);
};
}
要准备一个数组记录连接套接字的原因是:当select返回,有就绪套接字时,我们要将数组中的套接字拿出来循环测试,看看是那些套接字就绪,FD_ISSET
不然的话,连要FD_ISSET哪个都不知道。

Poll函数原型

#include<poll.h>
int poll(struct pollfd *fdarray,unsigned long nfds,int timeout)

struct pollfd{
int fd;
short events;
short revents;
struct pollfd fdarray[OPEN_MAX];
使用Poll,我们只需要分配一个pollfd结构的数组来维护客户信息即可,无需另外一个数组。这个也算是poll与select的区别了。
poll 和select 都是水平触发,当有事情发生就通知你,直到你把事情处理了。
其他poll select的区别都是老生常谈了,查看各大博文。
}

抱歉!评论已关闭.