UNIX网络编程读书笔记:select函数
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函数的更多相关文章
- UNIX网络编程--读书笔记
会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...
- UNIX网络编程读书笔记:简介
认知套接口编程接口 理解原始套接口(raw socket)的概念 值得注意的是,客户和服务器是典型的用户进程,而TCP和IP协议则通常是系统内核协议栈的一部分. 上图中在TCP和UDP之间留有间隙 ...
- Unix 网络编程 读书笔记1
第一章: C/C++语言提供两种不同的编程模式:IPL32和PL64.► IPL32 ● 表示integer/pointer/long三种数据类型是32位(4个字节),在这种模式下,提供32位的地址空 ...
- UNIX网络编程读书笔记:原始套接口
概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...
- UNIX网络编程读书笔记:套接口选项
概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...
- UNIX网络编程读书笔记:名字与地址转换
概述 在名字和数值地址间进行转换的函数: gethostbyname和gethostbyaddr:在主机名字与IPv4地址之间进行转换.仅仅支持IPv4. getservbyname和getservb ...
- UNIX网络编程读书笔记:poll函数
poll函数提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息. poll函数原型 #include <poll.h> int poll(struct pollfd * ...
- UNIX网络编程读书笔记:pselect函数
函数原型 pselect函数是由POSIX发明的,其原型如下: #include <sys/select.h> #include <signal.h> #include < ...
- UNIX网络编程读书笔记:shutdown函数
终止网络连接的通常方法是调用close函数.不过close有两个限制,却可以使用shutdown来避免. close 把描述字的引用计数减1,仅在该计数变为0时才关闭套接口.使用shutdown可以不 ...
随机推荐
- Linux中mysql的操作
一.mysql服务操作 二.数据库操作 三.数据表操作 四.修改表结构 五.数据备份和恢复 六.卸载数据库
- 「LOJ6482」LJJ爱数数
「LOJ6482」LJJ爱数数 解题思路 : 打表发现两个数 \(a, b\) 合法的充要条件是(我不管,我就是打表过的): \[ a + b = \text{gcd}(a, b)^2 \] 设 \( ...
- [BZOJ4873][六省联考2017]寿司餐厅(最大权闭合子图)
4873: [Shoi2017]寿司餐厅 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 490 Solved: 350[Submit][Status ...
- p1315构建双塔 dp
From easthong ☆构建双塔 描述 Description 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了 ...
- 【ArcGIS笔记】数据处理
1.ARCGIS在导入Excel坐标点的时候出现"没有注册类"的情况怎么办? 确保你本机上装有office,并且版本要能够识别XLSX格式.2007以上. 2.导入excel时re ...
- [转]Android Studio常用快捷键
(会持续更新)这边讲的常用快捷键是指做完Keymap到Eclipse后的,不是纯Android Studio的,这边主要讲下比较常用的一些快捷键: Ctrl+G / Ctrl+Alt+Shift+G: ...
- Educational Codeforces Round 12 E. Beautiful Subarrays 字典树
E. Beautiful Subarrays 题目连接: http://www.codeforces.com/contest/665/problem/E Description One day, ZS ...
- wampserver3.1.0安装及配置
安装篇 环境:win10 64位+wamp3.1.0 为什么安装wamp3.1.0呢?php7早已正式发布了,还没有尝过鲜呢.点击进入wampserver下载地址 本以为下载后,执行exe文件,点ne ...
- Android Studio安装后提示No JVM installation found解决办法
Android Studio安装后提示No JVM installation found解决办法 问题描述:Android Studio安装完毕,打开时出现提示"No JVM install ...
- CentOS 6.9通过RPM安装EPEL源(http://dl.fedoraproject.org)
另类的装法,通过RPM包直接安装 wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm & ...