作用:

实现I/O的多路复用

该函数允许进程指示内核等待多个事件中的任何一个发生,并只有在一个或多个事件发生时或经历一段指定的时间后才唤醒它。进程将于select处阻塞,直到被检测的描述符有一个或多个发生了变化。我们可以使用它来监视多个文件描述符的状态变化。

函数原型:

int select(int maxfd,fd_set *rdset,fd_set *wrset, \
fd_set *exset,struct timeval *timeout);

参数:

参数maxfd是需要监视的最大的文件描述符值+1;rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集 合及异常文件描述符的集合。struct timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。

下面的宏提供了处理这三种描述词组的方式:

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;//second
time_t tv_usec;//minisecond
};

这个参数有三种可能:

  • 永远等待下去:仅在一个描述符准备号I/O才返回。此时该参数为NULL
  • 等待一段固定时间:在有一个描述符准备好I/O时返回,但不超过由该参数所指向的timeval结构中指定的秒数和微秒数。
  • 不等待:检查描述符后立即返回。这称为轮询(polling)。此时该参数必须指向一个timeval结构,且两个值为0.

函数返回值

执行成功: 返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间。

执行失败: 当有错误时返回-1,错误原因存于errno中,此时参数readfds,writefds,exceptfds和timeout的值变成不可预测。错误值可能为:

  • EBADF 文件描述词为无效的或该文件已关闭
  • EINTR 此调用被信号所中断
  • EINVAL 参数n 为负值
  • ENOMEM 核心内存不足

示例

这里给出unp中基于select模型的echo服务器。

int main(int argc, char **argv)
{
//服务器初始化
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
socklen_t clilen; listenfd = Socket(AF_INET, SOCK_STREAM, 0); //TCP
struct sockaddr_in servaddr = InitSrvSockaddr(SERV_PORT), cliaddr;
Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ); maxfd = listenfd; //此时listenfd为fd最大值
maxi = -1; //index into client array
for (i = 0; i < FD_SETSIZE; ++i)
client[i] = -1; //初始化client数组 FD_ZERO(&allset);
FD_SET(listenfd, &allset); //listenfd 加入allset for (;;)
{
rset = allset;
nready = Select(maxfd + 1, &rset, NULL, NULL, NULL); //返回状态发生变化的描述符总数 if (FD_ISSET(listenfd, &rset)) //listenfd可用,代表有客户端连接成功
{
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *)&cliaddr, &clilen); for (i = 0; i < FD_SETSIZE; ++i) //从开始遍历client数组,找到第一个为-1的位置,将客户的fd保存
if (client[i] < 0) //为-1代表可用
{
client[i] = connfd;
break;
} if (i == FD_SETSIZE) //已满
err_quit("too many clients"); FD_SET(connfd, &allset);
if (connfd > maxfd)
maxfd = connfd;
if (i > maxi)
maxi = i;
if (--nready <= 0)
continue;
}
for (i = 0; i <= maxi; ++i)
{
if ((sockfd = client[i]) < 2)
continue;
if (FD_ISSET(sockfd, &rset))
{
if ((n = Read(sockfd, buf, MAXLINE)) == 0)
{
Close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
}
else
Writen(sockfd, buf, n);
if (--nready <= 0) //就绪描述符数目为0就跳出,避免检查未就绪的描述符
break;
}
}
}
}

参考自:

http://blog.csdn.net/turkeyzhou/article/details/8609360

《unix网络编程》

I/O复用之select的更多相关文章

  1. UNIX网络编程——I/O复用:select和poll函数

    我们看到TCP客户同时处理两个输入:标准输入和TCP套接字.我们遇到的问题是就在客户阻塞于(标准输入上)fgets调用,服务器进程会被杀死.服务器TCP虽然正确的给客户TCP发送了一个FIN,但是既然 ...

  2. 并发服务器--02(基于I/O复用——运用Select函数)

    I/O模型 Unix/Linux下有5中可用的I/O模型: 阻塞式I/O 非阻塞式I/O I/O复用(select.poll.epoll和pselect) 信号驱动式I/O(SIGIO) 异步I/O( ...

  3. 【Unix网络编程】chapter6 IO复用:select和poll函数

    chapter6 6.1 概述 I/O复用典型使用在下列网络应用场合. (1):当客户处理多个描述符时,必须使用IO复用 (2):一个客户同时处理多个套接字是可能的,不过不叫少见. (3):如果一个T ...

  4. UNIX网络编程 第6章 I/O复用:select和poll函数

    UNIX网络编程 第6章 I/O复用:select和poll函数

  5. Linux I/O复用中select poll epoll模型的介绍及其优缺点的比較

    关于I/O多路复用: I/O多路复用(又被称为"事件驱动"),首先要理解的是.操作系统为你提供了一个功能.当你的某个socket可读或者可写的时候.它能够给你一个通知.这样当配合非 ...

  6. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

  7. 第十七篇:IO复用之select实现

    前言 在看过前文:初探IO复用后,想必你已对IO复用这个概念有了初步但清晰的认识. 接下来,我要在一个具体的并发客户端中实现它(基于select函数),使得一旦服务器中的客户进程被终止的时候,客户端这 ...

  8. IO复用之select实现

    前言 在看过前文:初探IO复用后,想必你已对IO复用这个概念有了初步但清晰的认识.接下来,我要在一个具体的并发客户端中实现它( 基于select函数 ),使得一旦服务器中的客户进程被终止的时候,客户端 ...

  9. UNP学习笔记4——I/O复用:select和poll函数

    1 概述 之间的学习中发现,传统的阻塞式系统调用不仅浪费进程运行时间,而且会带来狠毒问题.因此进程需要有一种预先告知内核的能力,使得内核一旦发现进程指定的一个或者多个I/O条件就绪,它就通知进程.这个 ...

  10. linux的IO复用,select机制理解--ongoing

    一:首先需要搞清楚IO复用.阻塞的概念: Ref:  https://blog.csdn.net/u010366748/article/details/50944516 二:select机制 作为IO ...

随机推荐

  1. 省市区联动JS脚本

    省市区联动JS脚本 /* ***说明:省市区联动JS脚本 ***作者:Jerry Yuan  */ var province=[{id:0,name:'选择省'},{id:11,name:" ...

  2. centos7分区建议

    https://www.cnblogs.com/set-config/p/9040407.html

  3. Flex 画图

    <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="h ...

  4. 如何在notepad++实现代码自动化排版(调用Astyle)

    我先介绍这个怎么在notepad++中调用原版的astyle的方法. 在notepad++:运行或是F5, 在输入框中选择astyle.exe所在的目录,什么你没有astyle,下载地址https:/ ...

  5. Navicat for MySQL 安装和破解(完美)

    Navicat for MySQL 安装软件和破解补丁: 链接:https://pan.baidu.com/s/1oKcErok_Ijm0CY9UjNMrnA   密码:4xb1 navicat fo ...

  6. 基于Redis的Spring cache 缓存介绍

    目录 Cache API及默认提供的实现 demo 依赖包安装 定义实体类.服务类和相关配置文件 Cache注解 启用Cache注解 @CachePut @CacheEvict @Cacheable ...

  7. PHP中汉字截取

    $len = 19; $text = "怎么将新闻的很长的标题只显示前面一些字,后面用.....来代替?"; echo strlen($text)<=$len ? $text ...

  8. day14-函数

    1.定义函数 一个函数就是封闭一个功能def 函数名(): 函数代码注意:函数名不要用默认的关键字.否则会将默认关键字函数覆盖掉. 命名规则与变量相同,使用字母.数字.下划线组成,不能以数字开关 2. ...

  9. c# Type.InvokeMember用法

    函数原型: public object InvokeMember(string, BindingFlags, Binder, object, object[]);string:你所要调用的函数名Bin ...

  10. jquery接触初级----- 一种新奇的选择器用法

    今天看到一个新奇的jquery 选择器的用法,因为以前没有见过,所以记录下来 1.jquery 选择器: 给body添加一个元素,添加元素的时候,同时把属性和点击事件都一起进行添加 <!DOCT ...