select函数概况:

select函数允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个事件发生或经历一段指定的时间后才唤醒它。

作为一个例子,我们可以调用select,告知内核仅在下列情况发生时才返回:

(1)集合{1,4,5}中的任何描述字准备好读,或

(2)集合{2,7}中的任何描述字准备好写,或

(3)集合{1,4}中的任何描述字有异常条件待处理,或

(4)已经历了10.2秒。

也就是说,我们调用select告知内核对哪些描述字(就读、写或异常条件)感兴趣以及等待多长时间。我们感兴趣的描述字不局限于套接口;任何描述字都可以使用select来测试。

#include <sys/select.h>
#include <sys/time.h> int select(int maxfdpl, fd_set *readset, fd_set *writeset,
fd_set *exceptset, const struct timeval *timeout);
返回值:就绪描述字的总数目,0——超时,-1——出错

select函数参数介绍:

关于此函数的参数的详细介绍可参考http://www.cnblogs.com/nufangrensheng/p/3557584.html。重复内容不再赘述,这里只给出一些补充内容。

timeout参数的const限定词表示它在函数返回时不会被select修改。

但是有些Linux版本会修改这个timeval结构。因此从移植性考虑,我们应该假设该timeval结构在select返回时未被定义,因此每次调用select之前都得对它进行初始化。POSIX规定对该结构使用const限定词。

中间的三个参数readset、writeset和exceptset指定我们要让内核测试读、写和异常条件的描述字。目前支持的异常条件只有两个:

(1)某个套接口的带外数据的到达。

(2)某个已置为分组方式的伪终端存在可从其主端读取的控制状态信息。

如何给这三个参数的每一个指定一个或多个描述字值是一个设计上的问题。select使用描述字集,典型地是一个整数数组,其中每个整数中的每一位对应一个描述字。举例来说,假设使用32位整数,那么该数组的第一个元素对应描述字0-31,第二个元素对应描述字32-63,以此类推。所有这些实现细节都与应用程序无关,它们隐藏在名为fd_set的数据类型和以下四个宏中:

/* fd_set macro */
void FD_ZERO(fd_set *fdset); /* clear all bits in fdset */
void FD_SET(int fd, fd_set *fdset); /* turn on the bit for fd in fdset */
void FD_CLR(int fd, fd_set *fdset); /* turn off the bit for fd in fdset */
int FD_ISSET(int fd, fd_set *fdset); /* is the bit for fd on in fdset?*/

描述字集的初始化非常重要,因为作为自动变量分配的一个描述符字集如果没有初始化,那么可能发生不可预期的后果。因此,声明了一个描述符集后,必须用FD_ZERO清除其所有位,然后在其中设置我们关心的各个位。举个例子,以下代码用于定义一个fd_set类型的变量,然后打开描述字1、4和5的对应位:

/* example */
fd_set rset; FD_ZERO(&rset); /* initialize the set: all bits off */
FD_SET(1, &rset); /* turn on bit for fd 1 */
FD_SET(4, &rset); /* turn on bit for fd 4 */
FD_SET(5, &rset); /* turn on bit for fd 5 */

select函数的中间三个参数readset、writeset和exceptset中,如果我们对某一个的条件不感兴趣,就可以把它设为空指针。事实上,如果这三个指针均为空,我们就有了一个比UNIX的sleep函数更为精确的定时器(sleep睡眠以秒为最小单位)。poll函数提供类似的功能。

maxfdpl参数指定待测试的描述符字个数,它的值是待测试的最大描述符字加1(因此我们把该参数命名为maxfdpl),描述字0、1、2……一直到maxfdpl-1均被测试。

头文件<sys/select.h>中定义的FD_SETSIZE常值是数据类型fd_set中的描述字总数,其值通常是1024,不过很少有程序用到那么多描述字。

select函数修改由指针readset、writeset和exceptset所指向的描述字集,因而这三个参数都是值-结果参数。调用该函数时,我们指定所关心的描述字的值,该函数返回时,结果指示哪些描述字已就绪。该函数返回后,我们使用FD_ISSET宏来测试fd_set数据类型中的描述字。描述字集中任何与未就绪的描述字对应的位返回时均清成0。为此,每次重新调用select函数时,我们都得再次把所有描述字集中所关心的位均置为1。

使用select时最常见的两个错误:(1)忘了对最大描述字加1;(2)忘了描述字集是值-结果参数。

select函数返回值:

该函数的返回值表示跨所有描述字集的已就绪的总位数。如果在任何描述字就绪之前定时器时间到,那么返回0。返回-1表示出错。

描述字就绪条件:

1、下列四个条件中的任何一个满足时,一个套接口准备好读:

(1)该套接口接收缓冲区中的数据字节数大于等于套接口接收缓冲区低潮标记的当前大小。对这样的套接口的读操作将不阻塞并返回一个大于0的值(也就是返回准备好读入的数据)。我们可以使用SO_RCVLOWAT套接口选项设置该套接口的低潮标记。对于TCP和UDP套接口而言,其缺省值为1。

(2)该连接的读这一半关闭(也就是接收了FIN的TCP连接)。对这样的套接口的读操作将不阻塞并返回0(也就是返回EOF)。

(3)该套接口是一个监听套接口且已完成的连接数不为0。对这样的套接口的accept通常不会阻塞。

(4)其上有一个套接口错误待处理。对这样的套接口的读操作将不阻塞并返回-1(也就是返回一个错误),同时把errno设置成确切的错误条件。这些待处理的错误(pending error)也可以通过指定SO_ERROR套接口选项调用getsockopt获取并清除。

2、下列四个条件中的任何一个满足时,一个套接口准备好写:

(1)该套接口发送缓冲区中的可用空间字节数大于等于套接口发送缓冲区低潮标记的当前大小,并且或者(I)该套接口已连接,或者(II)该套接口不需要连接(例如UDP套接口)。这意味着如果我们把这样的套接口设置为非阻塞,写操作将不阻塞并返回一个正值(例如由传输层接受的字节数)。我们可以使用SO_SNDLOWAT套接口选项来设置该套接口的低潮标记。对于TCP和UDP而言,其缺省值通常为2048。

(2)该连接的写这一半关闭。对这样的套接口的写操作将产生SIGPIPE信号。

(3)该套接字早先使用非阻塞式connect已建立连接,并且连接已经异步建立或者connect已经以失败告终。

(4)其上有一个套接口错误待处理。对这样的套接口的写操作将不阻塞并返回-1(也就是返回一个错误),同时把errno设置成确切的错误条件。这些待处理的错误(pending error)也可以通过指定SO_ERROR套接口选项调用getsockopt获取并清除。

3、如果一个套接口存在带外数据或者仍处于带外标记,那么它有异常条件待处理。

注意:当某个套接口上发生错误时,它将由select标记为既可读又可写。

接收和发送低潮标记的目的在于:允许应用程序控制在select返回可读或可写条件之前,有多少数据可读或有多大空间可用于写。举例来说,如果我们知道除非至少存在64字节的数据,否则我们的应用程序没有任何工作可做,那么可以把接收低潮标记设置为64,以防少于64字节的数据准备好读时,select就唤醒我们。

任何UDP套接口只要其发送低潮标记小于等于发送缓冲区大小(缺省应该总是这种关系)就总是可写的,这是因为UDP套接口不需要连接。

UNIX网络编程读书笔记:select函数的更多相关文章

  1. UNIX网络编程--读书笔记

    会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...

  2. UNIX网络编程读书笔记:简介

    认知套接口编程接口 理解原始套接口(raw socket)的概念   值得注意的是,客户和服务器是典型的用户进程,而TCP和IP协议则通常是系统内核协议栈的一部分. 上图中在TCP和UDP之间留有间隙 ...

  3. Unix 网络编程 读书笔记1

    第一章: C/C++语言提供两种不同的编程模式:IPL32和PL64.► IPL32 ● 表示integer/pointer/long三种数据类型是32位(4个字节),在这种模式下,提供32位的地址空 ...

  4. UNIX网络编程读书笔记:原始套接口

    概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...

  5. UNIX网络编程读书笔记:套接口选项

    概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...

  6. UNIX网络编程读书笔记:名字与地址转换

    概述 在名字和数值地址间进行转换的函数: gethostbyname和gethostbyaddr:在主机名字与IPv4地址之间进行转换.仅仅支持IPv4. getservbyname和getservb ...

  7. UNIX网络编程读书笔记:poll函数

    poll函数提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息. poll函数原型 #include <poll.h> int poll(struct pollfd * ...

  8. UNIX网络编程读书笔记:pselect函数

    函数原型 pselect函数是由POSIX发明的,其原型如下: #include <sys/select.h> #include <signal.h> #include < ...

  9. UNIX网络编程读书笔记:shutdown函数

    终止网络连接的通常方法是调用close函数.不过close有两个限制,却可以使用shutdown来避免. close 把描述字的引用计数减1,仅在该计数变为0时才关闭套接口.使用shutdown可以不 ...

随机推荐

  1. 【BZOJ 3136】 3136: [Baltic2013]brunhilda (数论?)

    3136: [Baltic2013]brunhilda Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 238  Solved: 73[Submit][ ...

  2. JAVA中关于大数问题

    这里只是java速成,只限于java语法,包括输入输出,运算处理,字符串和高精度的处理,进制之间的转换等,能解决OJ上的一些高精度题目. 一.样例:java中的输出a+b import java.io ...

  3. Problem C: 深入浅出学算法004-求多个数的最小公倍数

    Description 求n个整数的最小公倍数 Input 多组测试数据,先输入整数T表示组数 然后每行先输入1个整数n,后面输入n个整数k1 k2...kn Output 求k1 k2 ...kn的 ...

  4. mpdf与fpdf的使用比较

    php扩展 ---mpdf/fpdf 最近用到pdf扩展,需求是生成合同与简历的pdf,可供下载打印 mpdf 首先接触的是mpdf,从源码可以看出mpdf是基于fpdf与html2fpdf的成果. ...

  5. hdu 4112 Break the Chocolate 贪心

    Break the Chocolate Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem. ...

  6. SpringMVC 3.1.1版本下的单元测试WEB-INF路径问题

    假设Spring配置文件为applicationContext.xml 一.Spring配置文件在类路径下面 在Spring的java应用程序中,一般我们的Spring的配置文件都是放在放在类路径下面 ...

  7. Java Web----Java Web的数据库操作(三)

    Java Web的数据库操作 前面介绍了JDBC技术和JDBC API及API的使用示例,下面详细介绍JDBC在Web中的应用. Java Web----Java Web的数据库操作(一) Java ...

  8. extjs grid数据改变后刷新的实现

    做了一个编辑extjs grid记录的窗体,但更改数据后,怎么重新刷新grid让数据显示呢? 做了半天的尝试,其实到最后只需一句话,faint:-) this.store.reload(); 不用加任 ...

  9. Mysql字符串连接函数 CONCAT()与 CONCAT_WS()

    从数据库里取N个字段,然后组合到一起用“,”分割显示,起初想到用CONCAT()来处理,好是麻烦,没想到在手册里居然有提到 CONCAT_WS(),非常好用. CONCAT_WS(separator, ...

  10. gdb -Mysql源代码级调试方法

    http://blog.csdn.net/hitzhang/article/details/5985474 gdb -q --batch --ex "set height 0" - ...