―――――――――――――――――――――――――――――――――――――――

2、select函数的接口比较简单:

int select(int nfds, fd_set *readset, fd_set *writeset,fd_set* exceptset, struct tim *timeout);

功能:

测试指定的fd可读?可写?有异常条件待处理?

参数:

nfds

需要检查的文件描述字个数(即检查到fd_set的第几位),数值应该比三组fd_set中所含的最大fd值更大,一般设为三组fd_set中所含的最大fd值加1(如在readset,writeset,exceptset中所含最大的fd为5,则nfds=6,因为fd是从0开始的)。设这个值是为提高效率,使函数不必检查fd_set的所有1024位。

readset

用来检查可读性的一组文件描述字。

writeset

用来检查可写性的一组文件描述字。

exceptset

用来检查是否有异常条件出现的文件描述字。(注:错误不包括在异常条件之内)

timeout

用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。

有三种可能:

1.timeout=NULL(阻塞:select将一直被阻塞,直到某个文件描述符上发生了事件)

2.timeout所指向的结构设为非零时间(等待固定时间:如果在指定的时间段里有事件发生或者时间耗尽,函数均返回)

3.timeout所指向的结构,时间设为0(非阻塞:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生)

返回值:

返回对应位仍然为1的fd的总数。

Remarks:

三组fd_set均将某些fd位置0,只有那些可读,可写以及有异常条件待处理的fd位仍然为1。

举个例子,比如recv(),   在没有数据到来调用它的时候,你的线程将被阻塞,如果数据一直不来,你的线程就要阻塞很久.这样显然不好. 所以采用select来查看套节字是否可读(也就是是否有数据读了)

步骤如下——

socket s;

.....

fd_set set;

while(1)

{

FD_ZERO(&set);//将你的套节字集合清空

FD_SET(s, &set);//加入你感兴趣的套节字到集合,这里是一个读数据的套节字s

select(0,&set,NULL,NULL,NULL);//检查套节字是否可读,

//很多情况下就是是否有数据(注意,只是说很多情况)

//这里select是否出错没有写

if(FD_ISSET(s, &set) //检查s是否在这个集合里面,

{ //select将更新这个集合,把其中不可读的套节字去掉

//只保留符合条件的套节字在这个集合里面

recv(s,...);

}

//do something here

}

理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。

(1)执行fd_set set; FD_ZERO(&set);则set用位表示是0000,0000。

(2)若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)

(3)若再加入fd=2,fd=1,则set变为0001,0011

(4)执行select(6,&set,0,0,0)阻塞等待

(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

基于上面的讨论,可以轻松得出select模型的特点:

(1)可监控的文件描述符个数取决与sizeof(fd_set)的值。我这边服务 器上sizeof(fd_set)=512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096。据说可调,另有说虽 然可调,但调整上限受于编译内核时的变量值。本人对调整fd_set的大小不太感兴趣,参考http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html中的模型2(1)可以有效突破select可监控的文件描述符上限。

(2)将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd,一是用于再select 返回后,array作为源数据和fd_set进行FD_ISSET判断。二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始 select前都要重新从array取得fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个 参数。

(3)可见select模型必须在select前循环array(加fd,取maxfd),select返回后循环array(FD_ISSET判断是否有时间发生)。

下面给一个伪码说明基本select模型的服务器模型:

array[slect_len];

nSock=0;

array[nSock++]=listen_fd;(之前listen port已绑定并listen)

maxfd=listen_fd;

while{

FD_ZERO(&set);

foreach (fd in array)

{

fd大于maxfd,则maxfd=fd

FD_SET(fd,&set)

}

res=select(maxfd+1,&set,0,0,0);

if(FD_ISSET(listen_fd,&set))

{

newfd=accept(listen_fd);

array[nsock++]=newfd;

if(--res=0) continue

}

foreach 下标1开始 (fd in array)

{

if(FD_ISSET(fd,&set))

执行读等相关操作

如果错误或者关闭,则要删除该fd,将array中相应位置和最后一个元素互换就好,nsock减一

if(--res=0) continue

}

}

使用select函数的过程一般是:

先调用宏FD_ZERO将指定的fd_set清零,然后调用宏FD_SET将需要测试的fd加入fd_set,接着调用函数select测试fd_set中的所有fd,最后用宏FD_ISSET检查某个fd在函数select调用后,相应位是否仍然为1。

以下是一个测试单个文件描述字可读性的例子:

int isready(int fd)

{

int rc;

fd_set fds;

struct tim tv;

FD_ZERO(&fds);

FD_SET(fd,&fds);

tv.tv_sec = tv.tv_usec = 0;

rc = select(fd+1, &fds, NULL, NULL, &tv);

if (rc < 0) //error

return -1;

return FD_ISSET(fd,&fds) ? 1 : 0;

}

下面还有一个复杂一些的应用:

//这段代码将指定测试Socket的描述字的可读可写性,因为Socket使用的也是fd

uint32 SocketWait(TSocket *s,bool rd,bool wr,uint32 timems)

{

fd_set rfds,wfds;

#ifdef _WIN32

TIM tv;

#else

struct tim tv;

#endif

FD_ZERO(&rfds);

FD_ZERO(&wfds);

if (rd) //TRUE

FD_SET(*s,&rfds); //添加要测试的描述字

if (wr) //FALSE

FD_SET(*s,&wfds);

tv.tv_sec=timems/1000; //second

tv.tv_usec=timems%1000; //ms

for (;;) //如果errno==EINTR,反复测试缓冲区的可读性

switch(select((*s)+1,&rfds,&wfds,NULL,

(timems==TIME_INFINITE?NULL:&tv))) //测试在规定的时间内套接口接收缓冲区中是否有数据可读

{ //0--超时,-1--出错

case 0:

return 0;

case (-1):

if (SocketError()==EINTR)

break;

return 0; //有错但不是EINTR

default:

if (FD_ISSET(*s,&rfds)) //如果s是fds中的一员返回非0,否则返回0

return 1;

if (FD_ISSET(*s,&wfds))

return 2;

return 0;

};

}

c语言FD_SET头文件,select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET相关推荐

  1. c语言的函数头书写标准,C语言的头文件的函数和书写方法.doc

    C语言的头文件的函数和书写方法 C语言头文件作用及写法 头文件几个好处: 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数:2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的 ...

  2. c语言memmove头文件,memmove函数

    写一个函数,完成内存之间的拷贝 void* mymemcpy( void *dest, const void *src, size_t count ) { char* pdest = static_c ...

  3. c语言exit头文件,exit函数在那个头文件

    c语言 exit的头文件是什么? C语言exit函数的头文件是stdlib.h. exit的声明为 void exit(int value); exit的作用是,退出程序,并将参数value的值返回给 ...

  4. c语言notify头文件,SendNotifyMessage()函数

    函数功能:该函数将指定的消息发送到一个窗口.如果该窗口是由调用线程创建的:此函数为该窗口调用窗口程序,并等待窗口程序处理完消息后再返回.如果该窗口是由不同的线程创建的,此函数将消息传给该窗口程序,并立 ...

  5. c语言中ndigit用法,求C语言中头文件及函数的含意的总分类

    ALLOC.H 说明内存管理函数(分配.释放等). ASSERT.H 定义 assert调试宏. BIOS.H 说明调用IBM-PC ROM BIOS子程序的各个函数. CONIO. H 说明调用DO ...

  6. c语言中错误为ffblk未定义,C语言中头文件及函数的含意的总分类

    ALLOC.H 说明内存管理函数(分配.释放等). ASSERT.H 定义assert调试宏. BIOS.H 说明调用IBM-PC ROM BIOS子程序的各个函数. CONIO.H 说明调用DOS控 ...

  7. linux 查看socket fd,linux socket中select()函数以及FD_ZERO FD_SET FD_CLR FD_ISSET

    linux socket非阻塞编程时常见到如下的code: socket   s; ..... fd_set   set; ..... struct timeval tv; while(1) { FD ...

  8. C语言再学习 -- 常用头文件和函数(转)

    参看:C/C++常用头文件及函数汇总 linux常用头文件如下: POSIX标准定义的头文件 <dirent.h>        目录项 <fcntl.h>         文 ...

  9. C语言的头文件和库文件(函数库)

    C语言的头文件和库文件(函数库) 分类: Unix环境高级编程 2011-04-17 14:37 2576人阅读 评论(1) 收藏 举报 语言cgcclinuxunix 在C语言中,头文件提供对常量的 ...

  10. 在c语言中怎么返回引用参数,C语言函数 函数的声明 C语言的头文件 #include的用法 形参和实参 函数的返回值 - 猫扑天空...

    C语言函数 一.是什么? 是指编程中对一块功能代码的封装,可以理解一个程序片段 二.有什么用? 可以封装代码,方便调用,提高复用性 三.怎么用? 定义:  返回值类型  函数名(形参类型 参数名1-. ...

最新文章

  1. 把软件架构演进体现在栈上
  2. mysql 查询结果行变列_SQL 查询怎么将行变成列
  3. 打印所有低于平均分的分数(数组)
  4. HDU 2003 求绝对值
  5. Rails 3.1 CoffeeScript SASS初体验
  6. java面向对象的多态_java面向对象(五)之多态
  7. Python基础---循环、条件判断
  8. 在LoadRunner里何时该用 .NET Vuser协议?
  9. SWPU ROUND #6(DIV.3)
  10. 重物码垛搬运机器人_米克力美AGV:工业机器人的应用场景
  11. vue开发:前端项目模板
  12. 关于招标说明书的撰写要点
  13. 华为存储系统操作管理
  14. 边缘计算是什么?边缘计算系统的组成及概念
  15. 怎样成为优秀的测试工程师
  16. Java Annotation自定义注解详解
  17. 计算机课拔线头检讨书,电脑显示器上出现检测信号线应该怎么解决?
  18. application.properties详解 --springBoot配置文件
  19. CSS linear-gradient 实现背景双色或多色,颜色渐变,颜色分明
  20. 《褚时健传》读书笔记

热门文章

  1. 开灯问题~有n盏灯,编号为1~n。1号将灯全部打开,2将按下所有为2的倍数的开关,(这些灯将被关掉)第3个人按下所有编号为3的倍数的开关(该灯如为打开的, 则将它关闭;如关闭的,则将它打开)。
  2. Requested setting DATABASES, but settings are not configured. You must either define the environment
  3. WebRTC的拥塞控制和带宽策略
  4. 用友NC系统与一卡通集成解决方案
  5. JVM 参数学习--实际参数设置
  6. 扭曲丛林服务器未响应,LOL等级最高玩家已246级 狂刷扭曲丛林攒经验
  7. 2023北京眼镜展览会暨首届智能眼镜展览会
  8. #pragma comment
  9. Lorenzo Von Matterhorn
  10. C语言每日一练 —— 第21天:算法的应用