浅谈IO多路转接之select-----基础网络

一、select原型

#include<sys/select.h>
int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);

二、参数解释:

        1.参数nfds是需要监视的最大文件描述值+1;

        2.rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合;

        3.参数timeout为结构timeval,用来设置select()的等待时间。

三、参数timeout取值

        1.NULL:表示select()没有timeout,select将一直被阻塞,直到某个文件描述符发生了事件;

        2.0:仅检测描述符的状态,然后立即返回,并不等待外部事件的发生;

        3.特定的实际值:如果在指定的时间段里没有事件发生,select将超时返回。

四、fd_set结构

        其实这个结构就是一个整型数组,更严格的说,是一个“位图”,使用位图中对应的位表示要监视的文件描述符。

select中fd_set结构不能使用与、或、非操作,只能使用相对应的操作:

1.用来消除描述词组 set中相关fd的位;

void FD_CLR(int fd,fd_set *set);

2.用来测试描述词组set中的相关fd的位是否为真;

void FD_ISSET(int fd,fd_set *set);

3.用来设置描述词组set中相关的位;

void FD_SET(int fd,fd_set *set);

4.用来消除描述词组set的全部位;

void FD_ZERO(int fd,fd_set *set);

五、函数返回值

        1.执行成功则返回文件描述符状态已经改变的个数;

        2.如果返回0代表在描述词状态改变之前已经超过 timeout时间,没有返回;

        3.当有错误发生时则返回-1,错误原因存于error,此时参数readfd、writefd、exceptfd和timeout的值变成不可预测

六、socket就绪条件

读就绪:

        1.socket内核中,接收缓冲区中的字节数,大于等于低水位标记SO_RCVLOWAT。此时就可以无阻塞的读该文件描述符,并且返回值大于0;

        2.socket TCP通信中,对端关闭连接,此时对该socket读,则返回0(四次挥手);

        3.监听的socket上有新的连接请求;

        4.socket上有未处理的错误。

写就绪:

        1.socket内核中,发送缓冲区中的可用字节数(发送缓冲区的空闲位置大小),大于等于低水位标记SO_RCVLOWAT。此时可以无阻塞的写,并且返回值大于0;

        2.socket的写操作被关闭。对一个写操作被关闭的socket进行写操作,会触发SIGPIPE信号;

        3.socket使用非阻塞connect连接成功或失败之后;

        4.socket上有未读取的错误;

异常就绪:

        socket上带外数据。关于带外数据,和TCP紧急模式相关(TCP协议头中的紧急指针字段)。

七、select的特点

        1.可监控的文件描述符个数取决于sizeof(fdset)的值;

        2.将fd假如select监控集的同时,还要使用一个数据结构array保存放到 select监控集中的fd。

八、select缺点

        1.每次调用select,都需要手动设置fd集合,从接口使用角度来说非常不便;

        2.每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd时会很大;

        3.同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大;

        4.select支持的文件描述符数量有限。


猜你喜欢

转载自blog.csdn.net/cyd_csdn/article/details/80464465