当前位置:首页 >> IT/计算机 >>

linux Select函数用法详解


SocketSocket-Select
Select 在 Socket 编程中还是比较重要的,可是对于初学 Socket 的人来说都不 太爱用 Select 写程序, 他们只是习惯写诸如 connect、 accept、 recv 或 recvfrom 这样的阻塞程序(所谓阻塞方式 block,顾名思义,就是进程或是线程执行到这 些函数时必须等 待某个事件的发生,如果事

件没有发生,进程或线程就被阻塞, 函数不能立即返回)。 可是使用 Select 就可以完成非阻塞(所谓非阻塞方式 non-block,就是 进程或线程执行此函数时不必非要等待事件的发生, 一旦执行肯定返回, 以返 回 值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有 发生则返回一个代码来告知事件未发生, 而进程或线程继续执行, 所以效率较高) 方式工作的程序, 它能够监视我们需要监视的文件描述符的变化情况——读写或 是异常。下面详细介绍一下。 Select 的函数格式: int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout); 先说明两个结构体: 第一,struct fd_set 可以理解为一个集合,这个集合中存放的是文件描述符 (file descriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然 Unix 下任何设备、管道、FIFO 等都是文件形式,全部包括在内,所以毫 无疑问 一个 socket 就是一个文件,socket 句柄就是一个文件描述符。fd_set 集合可以 通过一些宏由人为来操作,比如清空集合 FD_ZERO(fd_set *),将一个给定的文 件描述符加入集合之中 FD_SET(int ,fd_set *),将一个给定的文件描述符从集 合中删除 FD_CLR(int ,fd_set*),检查集合中指定的文件描述符是否可以读写 FD_ISSET(int ,fd_set* )。一会儿举例说明。 第二,struct timeval 是一个大家常用的结构,用来代表时间值,有两个成员, 一个是秒数,另一个是毫秒数。 具体解释 select 的参数: int maxfdp 是一个整数值,是指集合中所有文件描述符的范围,即所有文件描 述符的最大值加 1,不能错!在 Windows 中这个参数的值无所谓,可以设置不正 确。 fd_set *readfds 是指向 fd_set 结构的指针,这个集合中应该包括文件描述符, 我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中 读取数据了,如果这个集合中有一个文件可读,select 就会返回一个大于 0 的 值,表示有文件可读,如果没有可读的文件,则根据 timeout 参数再判断 是否

超时,若超出 timeout 的时间,select 返回 0,若发生错误返回负值。可以传入 NULL 值,表示不关心任何文件的读变化。 fd_set *writefds 是指向 fd_set 结构的指针, 这个集合中应该包括文件描述符, 我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件 中 写入数据了,如果这个集合中有一个文件可写,select 就会返回一个大于 0 的 值,表示有文件可写,如果没有可写的文件,则根据 timeout 参数再判 断是否 超时,若超出 timeout 的时间,select 返回 0,若发生错误返回负值。可以传入 NULL 值,表示不关心任何文件的写变化。 fd_set *errorfds 同上面两个参数的意图,用来监视文件错误异常。 struct timeval* timeout 是 select 的超时时间,这个参数至关重要,它可以 使 select 处于三种状态,第一,若将 NULL 以形参传入,即不传入时间结构,就 是 将 select 置于阻塞状态, 一定等到监视文件描述符集合中某个文件描述符发 生变化为止; 第二, 若将时间值设为 0 秒 0 毫秒, 就变成一个纯粹的非阻塞函数, 不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回 0,有变化 返回一个正值;第三,timeout 的值大于 0,这就是等待的超时时间,即 select 在 timeout 时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管 怎样一定返回,返回值同上述。 返回值: 负值:select 错误 正值:某些文件可读写或出错 0:等待超时,没有可读写或错误的文件 在有了 select 后可以写出像样的网络程序来!举个简单的例子,就是从网络上 接受数据写入一个文件中。 例子: main() { int sock; FILE *fp; struct fd_set fds; struct timeval timeout={3,0}; //select 等待 3 秒,3 秒轮询,要非阻塞就置

0 char buffer[256]={0}; //256 字节的接收缓冲区 /* 假定已经建立 UDP 连接,具体过程不写,简单,当然 TCP 也同理,主机 ip 和 port 都已经给定,要写的文件已经打开 sock=socket(...); bind(...); fp=fopen(...); */ while(1) { FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化 FD_SET(sock,&fds); //添加描述符 FD_SET(fp,&fds); //同上 maxfdp=sock>fp?sock+1:fp+1; //描述符最大值加 1 switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select 使用 { case -1: exit(-1);break; //select 错误,退出程序 case 0:break; //再次轮询 default: if(FD_ISSET(sock,&fds)) //测试 sock 是否可读,即是否网络上有数据 { recvfrom(sock,buffer,256,.....);//接受网络数据 if(FD_ISSET(fp,&fds)) //测试文件是否可写 fwrite(fp,buffer...);//写入文件

//buffer 清空; } // end if break; } // end switch } //end while } //end main
由于采用 select 机制, 因此当没有字符可读时, 程序处于阻塞状态,最小程度的占用 CPU 资源, 在同一台机器上执行一个 server 和若干个 client 时, 系统负载只有 0.1 左右, 而采 用原来的非阻塞通信方法, 只运行一个 server, 系统负载就可以达到 1.5 左右. 因此我们推 荐使用 select。

socket select()用法 用法
头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<unistd.h> 定义函数 int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout); 函数说明 select()用来等待文件描述词状态的改变。参数 n 代表最大的文件描述词加 1, 参数 readfds、writefds 和 exceptfds 称为描述词组,是用来回传该描述词的 读,写或例外的状况。底下的宏提供了处理这三种描述词组的方式: FD_CLR(inr fd,fd_set* set);用来清除描述词组 set 中相关 fd 的位 FD_ISSET(int fd,fd_set *set);用来测试描述词组 set 中相关 fd 的位是否为 真 FD_SET(int fd,fd_set*set);用来设置描述词组 set 中相关 fd 的位 FD_ZERO(fd_set *set); 用来清除描述词组 set 的全部位 参数 timeout 为结构 timeval,用来设置 select()的等待时间,其结构定义如下 struct timeval {

time_t tv_sec; time_t tv_usec; }; 返回值 如果参数 timeout 设为 NULL 则表示 select()没有 timeout。 错误代码 执行成功则返回文件描述词状态已改变的个数, 如果返回 0 代表在描述词状态改 变前已超过 timeout 时间,当有错误发生时则返回-1,错误原因存于 errno,此 时参数 readfds,writefds,exceptfds 和 timeout 的值变成不可预测。 EBADF 文件描述词为无效的或该文件已关闭 EINTR 此调用被信号所中断 EINVAL 参数 n 为负值。 ENOMEM 核心内存不足 范例 常见的程序片段:fs_set readset; FD_ZERO(&readset); FD_SET(fd,&readset); select(fd+1,&readset,NULL,NULL,NULL); if(FD_ISSET(fd,readset){……} 下面是 linux 环境下 select 的一个简单用法 #include #include #include #include #include #include <sys/time.h> <stdio.h> <sys/types.h> <sys/stat.h> <fcntl.h> <assert.h>

int main () { int keyboard; int ret,i; char c; fd_set readfd; struct timeval timeout; keyboard = open("/dev/tty",O_RDONLY | O_NONBLOCK); assert(keyboard>0); while(1)

{ timeout.tv_sec=1; timeout.tv_usec=0; FD_ZERO(&readfd); FD_SET(keyboard,&readfd); ret=select(keyboard+1,&readfd,NULL,NULL,&timeout); if(FD_ISSET(keyboard,&readfd)) { i=read(keyboard,&c,1); if('\n'==c) continue; printf("hehethe input is %c\n",c); if ('q'==c) break; } } }


相关文章:
Linux下select函数的使用
Linuxselect函数的使用_计算机软件及应用_IT/计算机_专业资料。Linuxselect 函数的使用 select 系统调用是用来让我们的程序监视多个文件句柄的状态变化的。程序...
linux下c语言select函数用法
linux 下 c 语言 select 函数用法 select( 多工机制) select(I/O 多工机制...timeout); select()用来等待文件描述词状态的改变 用来等待文件描述词状态的改变...
Linux socket select 函数用法详解
Linux socket select 函数用法详解_计算机软件及应用_IT/计算机_专业资料。LINUX socket select 详解linux 的 socket 函数分为阻塞和非阻塞两种方式,比如 accept 函数...
C++网络编程Select函数用法详解
C++网络编程Select函数用法详解_IT/计算机_专业资料。C++网络编程Select函数用法...{...} } 二、linux c 中 select(I/O 多工机制) 表头文件 #i nclude<...
linux中select函数的使用
linuxselect函数的使用linuxselect函数的使用隐藏>> linuxselect 函数的使用 Select 在 Socket 编程中还是比较重要的,可是对于初学 Socket 的人来说都不 太...
linux中select函数
linuxselect函数_IT/计算机_专业资料。select 函数: 系统提供 select 函数来实现...(2)将 fd 加入 select 监控集的同时,还要再使用一个数据结构 array 保存放到...
windows编程中select函数的使用
windows编程中select函数的使用_计算机软件及应用_IT/计算机_专业资料。socket select...{...} } 二、linux c 中 select(I/O 多工机制) 表头文件 #i nclude<...
Linux后台网络编程中select
喜欢此文档的还喜欢 linux下文件传送程序代码... 6页 1下载券 Linux下文件...使用 select 完成非阻塞方式 IO (non-block,进程或线程执行此函数时不必非要等待...
linux select 语句
linux select 语句_信息与通信_工程科技_专业资料。结构介绍@的用法( linux select用法(转) select()函数主要是建立在 fd_set 类型的基础上的。fd_set(它 ...
Linux下select函数实现的聊天服务器
Linuxselect函数实现的聊天服务器_IT/计算机_专业资料。Linux select函数Linuxselect 函数实现的聊天服务器 Linuxselect 函数实现的聊天服务器 Windows 下...
更多相关标签:
linux select函数详解 | linux select用法 | linux select详解 | select 函数用法 | select函数详解 | js select 函数用法 | select函数的用法 | sql select 函数用法 |