首页 > 代码库 > I/O多路复用的解决方法--select

I/O多路复用的解决方法--select

ubuntu12.04

在实际情况中,人们往往遇到多个客户端连接服务器端的情况。由于如connet()、recv()和send() 、accept()等都是阻塞性函数,如果资源没有准备好,则调用该函数的进程将进入睡眠状态,这样就无法处理I/O多路复用的情况了。

使用fcntl()函数虽然可以实现非阻塞I/O或信号驱动I/O,但在实际使用时往往会对资源是否准备完毕进行循环测试,这样就大大增加了不必要的CPU资源的占用。在这里可以使用select()函数来解决这个问题,同时,使用select()函数还可以设置等待的时间,可以说功能更加强大。

 

所在库:

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
 
 函数原型:
int select(int n, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);
n 最大文件描述符+1
read_fds      读文件描述符集合 (scanf  recv)
write_fds     写文件描述符集合
except_fds  异常文件描述符
timeout        超时设置.
 
Null:一直阻塞,直到有文件描述符就绪或出错
时间值为0:仅仅检测文件描述符集的状态,然后立即返回  
时间值不为0:在指定时间内阻塞,如果没有事件发生,则超时返回。

 

 

示例:

#include <sys/time.h>
struct timeval tv;
 /* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);


返回值为>0 就是有事件发生,有几个文件描述符发生了变化
      =0 超时返回

       -1 出错
 
集合变量类型:fd_set r_fds;
集合变量运算宏:
FD_ZERO(&r_fds )
FD_SET(把某一个FD, 加入监控)
FD_ISSET(FD, fd_set),判断现在文件描述符对应的文件是不是有变化,如果有,返回值为真,无则假
FD_CLR

I/O多路复用的解决方法--select