select函数及fd_set介绍
1. select函数
1. 用途
在编程的过程中,经常会遇到许多阻塞的函数,好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,当函数不能成功执行的时候,程序就会一直阻塞在这里,无法执行下面的代码。这时就需要用到非阻塞的编程方式,使用select函数就可以实现非阻塞编程。
select函数是一个轮循函数,循环询问文件节点,可设置超时时间,超时时间到了就跳过代码继续往下执行。
2. 大致原理
select需要驱动程序的支持,驱动程序实现fops内的poll函数。select通过每个设备文件对应的poll函数提供的信息判断当前是否有资源可用(如可读或写),如果有的话则返回可用资源的文件描述符个数,没有的话则睡眠,等待有资源变为可用时再被唤醒继续执行。详细的原理请看这里
3. 函数定义
该函数声明如下
int select(int nfds, fd_set *readset, fd_set *writeset, fe_set* exceptset,
struct timeval* timeout);
参数:
nfds 需要检查的文件描述字个数
readset 用来检查可读性的一组文件描述字。
writeset 用来检查可写性的一组文件描述字。
exceptset 用来检查是否有异常条件出现的文件描述字。(注:错误不包括在异常条件之内)
timeout 超时,填NULL为阻塞,填0为非阻塞,其他为一段超时时间
返回值:
返回fd的总数,错误时返回SOCKET_ERROR
2. fd_set结构体
上面select函数中需要用到两个fd_set形参,这个结构体到底做什么用的呢
fd_set其实这是一个数组的宏定义,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(socket、文件、管道、设备等)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪个句柄可读。
系统提供了FD_SET, FD_CLR, FD_ISSET, FD_ZERO进行操作,声明如下:
FD_SET(int fd, fd_set *fdset); //将fd加入set集合
FD_CLR(int fd, fd_set *fdset); //将fd从set集合中清除
FD_ISSET(int fd, fd_set *fdset); //检测fd是否在set集合中,不在则返回0
FD_ZERO(fd_set *fdset); //将set清零使集合中不含任何fd
下面写一段程序探究一下这几个宏的工作:
#include <WINSOCK2.H>int main()
{fd_set fdset;FD_ZERO(&fdset);FD_SET(1, &fdset);FD_SET(2, &fdset);FD_SET(3, &fdset);FD_SET(7, &fdset);int isset = FD_ISSET(3, &fdset);printf("isset = %d\n", isset);FD_CLR(3, &fdset);isset = FD_ISSET(3, &fdset);printf("isset = %d\n", isset);return 0;
}
当使用FD_SET添加完1、2、3、7后,fdset的值如下:
然后经过FD_CLR以后,fd_array[2]就被清除了,数组后面的数据一次往前提,即7被放到了fd_array[2]
所以isset前后两次打印的值分别为1和0
3. 小结
select的结果会对fd_set造成影响。例如,对于一个监听的socket:
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib,"WS2_32.lib")
int main()
{FD_SET ReadSet;FD_ZERO(&ReadSet);WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData); //初始化SOCKET ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); //定义一个监听套接字//bind 等操作这里省略.... //......FD_SET(ListenSocket, &ReadSet); //将套接字加入ReadSet集合中int isset = FD_ISSET(ListenSocket, &ReadSet); //这里并没有通过select对fd_set进行筛选 printf("Before select, isset = %d\n", isset); //所以这里打印结果为1 struct timeval tTime; tTime.tv_sec = 10; tTime.tv_usec = 0; select(0, &ReadSet, NULL, NULL, &tTime); //通过select筛选处于就绪状态的fd //这时,刚才的ListenSocket并不在就绪状态(没有连接连入),那么就从ReadSet中去除它 isset = FD_ISSET(ListenSocket, &ReadSet); printf("After select, isset = %d\n", isset); //所以这里打印的结果为0 system("pause"); return 0;
}
所以可以使用select以及fd的操作来完成异步的网络消息处理,具体的实现请看这里的例子
select函数及fd_set介绍相关推荐
- Linux下IO多路复用之select函数的使用
select函数的作用: 如果我们的程序里有两个需要阻塞的地方,例如要从服务器读数据,同时还要从键盘上读数据(若不采用阻塞而用查询的方式则大量占用系统资源).这个时候我们就有两处阻塞,你当然可以用多线 ...
- Linux select函数的使用
文章目录 一.select函数 1.fd_set结构体 FD_ZERO FD_SET FD_CLR FD_ISSET 2.timeval 结构体 3.返回值 二.文件描述符就绪条件 三.使用 一.se ...
- select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型, 原型: int select(int maxfd,fd_set *rds ...
- select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...
- linux中有fd set函数吗,LINUX下FD_SET介绍
刚刚了解了linux下select系统调用,函数原型是 #include #include int select(int maxfdpl, fd_set *readset, fd_set *write ...
- select函数介绍
linux编程中select函数用于检测一组socket上是否有事件就绪,这里的事件包括可读.可写.异常事件,其中读事件就绪是指发生以下几种情况: 1. socket内核接收缓冲区的字节数大于等于低水 ...
- Linux延时(延迟)函数比较:介绍Linux系统中常用的延时函数sleep、usleep、nanosleep、select和std::sleep_for()的区别和使用场景
首先,需要了解各个睡眠函数的作用和使用场景. sleep函数用于让进程休眠指定的秒数,适用于需要较长时间的休眠场景: usleep函数用于让进程休眠指定的微秒数,适用于需要较短时间的休眠场景,不精确: ...
- Select函数实现原理分析
转载自 http://blog.chinaunix.net/uid-20643761-id-1594860.html select需要驱动程序的支持,驱动程序实现fops内的poll函数.select ...
- socket通信时如何判断当前连接是否断开--select函数,心跳线程,QsocketNotifier监控socket...
client与server建立socket连接之后,如果突然关闭server,此时,如果不在客户端close(socket_fd),会有不好的影响: QsocketNotifier监控socket的槽 ...
最新文章
- webp、jpeg、png三种压缩算法比较
- 关于CRTP(Curiously Recurring Template Prattern)的使用
- JNDI 在 J2EE 中的角色
- [BZOJ1643][Usaco2007 Oct]Bessie's Secret Pasture 贝茜的秘密草坪
- JQ:当页面滚动到一定位置之后,让元素固定在顶部,小于位置后恢复原来的位置
- python将2个列表list合并到1个列表使用appenden_【新手入门】20个很实用的 Python 学习小技巧...
- android 录音原始文件_5分钟短文 | Android证书生成,签名,验证,虽然难,但学一次就够了!...
- cf1523A. Game of Life
- CISCO PVST+配置和结果验证 per vlan spanning tree(51cto 实验10)
- 用css3和jquery实现的渐变的动态进度条
- GPU服务器的配置计划
- java检测textarea换行_Textarea和Java 换行符
- 基于HT for Web矢量实现3D叶轮旋转
- 使用rarcrack暴力破解RAR,ZIP,7Z压缩包
- 登录oneNote失败解决
- 网易云ncm转mp3
- WT588D语音芯片 语音模块组
- Excel技巧—快速插入空行技巧大集合
- Speedoffice(Excel)怎样给文字添加删除线?
- 如何查看tkinter可用的字体有哪些
热门文章
- spark的内存过小报错
- Codeup墓地-问题 A: 最长上升子序列
- 【易懂】Java源码角度分析put()与putIfAbsent()的区别——源码分析系列
- [leetcode]106.从中序与后序遍历序列构造二叉树
- DBSAN密度聚类算法
- 数据库原理与应用(SQL Server)笔记 第七章 流程控制语句、系统内置函数
- linux curl 多线程,CURL多线程不执行一直在请求
- java中字符串的操作_java中字符串的操作
- tomcat日志、控制台乱码
- 教室工资管理系统c语言课程设计csdn,工资管理系统(C编写)