select模型支持IO多路复用,select函数如下

int select (
IN int nfds, //windows下无意义,linux有意义
IN OUT fd_set* readfds, //检查可读性
IN OUT fd_set* writefds, //检查可写性
IN OUT fd_set* exceptfds, //例外数据
IN const struct timeval* timeout); //函数的返回时间

逐个解释每个参数意义:

nfds:一个整型变量,表示比最大文件描述符+1

readfds: 这个集合监测读事件的描述符,将要监听

读事件的文件描述符放入readfds中,通过调用select,

readfds中将没有就绪的读事件文件描述符清除,留下

就绪的读事件描述符,可以通过read或者recv来处理

writefds:这个集合监测写事件的描述符,将要监听的

写事件的文件描述符放入writefds中,通过调用select,

writefds中没有就绪的写事件文件描述符被清除,留下

就绪的写事件描述符,可以通过write或者send来处理。

execptfds:这个集合在调用select后会存有错误的文件

描述符。根据Linux网络网络编程第二版中介绍,可以

监视带外数据OOB,带外数据使用MSG_OOB标志发送

到套接字上,当select()函数返回的时候,readfds将清除

其中的其他文件描述符,留下OOB数据

函数返回值:

当返回0时表示超时,-1表示有错误,大于0表示没有错误。

当监视文件集中有文件描述符符合要求,即读文件描述符集

合中有文件可读,写文件描述符集合中有文件可写,或者

错误文件描述符集合中有错误的描述符,都会返回大于0的数。

timeval结构体解释

struct  timeval {
long tv_sec; //秒
long tv_usec; //毫秒
};

timeval指针为NULL,表示一直等待,直到有符合条件的描述符

触发select返回

如果timeval中个参数均为0,表示立即返回,否则在select没有

符合条件的描述符,等待对应的时间和,然后返回。

另外需要了解一些select的操作宏函数

fd_set是一个SOCKET队列,以下宏可以对该队列进行操作:
FD_CLR( s, fd_set *set) 从队列set删除句柄s;
FD_ISSET( s,fd_set *set) 检查句柄s是否存在与队列set中;
FD_SET( s, fd_set *set )把句柄s添加到队列set中;
FD_ZERO( fd_set *set ) 把set队列初始化成空队列.

看一个select的使用示例

//前面是服务器socket的创建,绑定和监听

int  listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind local.sin_family = AF_INET;
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_port = htons(PORT);
bind(listenSocket, (sockaddr*)&local, sizeof(SOCKADDR_IN)); // Listen listen(listenSocket, );
//设置非阻塞
fcntl(listenSocket, F_SETFL, O_NONBLOCK ); //这个使用来统计所有已经连接上来的文件描述符,
//也可以用数组表示,只是遍历的时候要根据数据结构进行更改
FD_SET socketSet;
FD_SET writeSet;
FD_SET readSet; //清空 socketSet
FD_ZERO(&socketSet);
//将文件描述符放入 socketSet,
//用于accept
FD_SET(listenSocket,&socketSet);
//统计最大的socket
int maxfd = listenSocket;
int conNum = ;
//数组存储连接的socket
int connectArray[]={};
while(true)
{
//清空读写集合
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
//读写都监听
readSet=socketSet;
writeSet=socketSet; //同时检查套接字的可读可写性。
//为等待时间传入NULL,则永久等待。传入0立即返回。不要勿用。
int ret=select(maxfd,&readSet,&writeSet,NULL,NULL);
if(ret==-)
{
return false;
}
sockaddr_in addr;
int len=sizeof(addr);
//是否存在客户端的连接请求。
//在readset中会返回已经调用过listen的套接字
if(FD_ISSET(listenSocket,&readSet))
{
acceptSocket=accept(listenSocket,(sockaddr*)&addr,&len);
if(acceptSocket==INVALID_SOCKET)
{
return false;
}
else
{
//大于我们最大的监听数量了
if(conNum > )
{
return false;
}
//更新数组
connectArray[conNum] = acceptSocket;
//设置非阻塞
fcntl(connectArray[conNum], F_SETFL, O_NONBLOCK );
//加到socketset里,以后赋值给读写集合
FD_SET(connectArray[conNum],&socketSet);
if(acceptSocket > maxfd)
{
maxfd = acceptSocket;
}
conNum++;
}
} for(int i=;i<conNum;i++)
{
//判断是否有读事件
if(FD_ISSET(connectArray[i],&readSet))
{
//调用recv,接收数据。
//判断recv结果,为0则客户端断开,
//那么调用FD_CLR并关闭对应的socket
}
//判断是否有写事件
if(FD_ISSET(connectArray[i],&writeSet)
{
//调用send,发送数据。
//判断send结果,为0客户端断开,
//那么调用FD_CLR并关闭对应的socket
}
}
}

上面的例子结合了网上提供的一些demo,其实writeSet不一定要放入socket,当某个socket需要send内容时

再调用FD_SET(socket,&writeSet),写成功后再调用FD_CLR(socket,&writeSet);避免造成busyloop,

因为当缓冲区非空时,写事件是一直就绪的。

我的微信公众号,定期推送一些技术总结,一起努力吧。

select网络模型知识总结的更多相关文章

  1. linux select 网络模型

    io模型: 同步IO: 阻塞形式,非阻塞形式(轮询).信号驱动IO.IO复用(select, poll, epoll): 异步io:aio_read() 典型场景: 1.客户端处理多种IO------ ...

  2. python 3下基于select模型的事件驱动机制程序

    它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程.它的流程如图: 当用户进程调用了select,那么整个 ...

  3. EasyDarwin开源流媒体server将select改为epoll的方法

    本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听全部网络读写事件.Even ...

  4. EasyDarwin开源流媒体服务器将select改为epoll的方法

    本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听所有网络读写事件,Even ...

  5. 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能

    经过春节前后将近2个月的开发和稳定调试.测试,EasyDarwin开源流媒体服务器终于成功将底层select网络模型修改优化成epoll网络模型,将EasyDarwin流媒体服务器在网络处理的效率上提 ...

  6. Django源码分析之启动wsgi发生的事

    前言 ​ 好多人对技术的理解都停留在懂得使用即可,因而只会用而不会灵活用,俗话说好奇害死猫,不然我也不会在凌晨1.48的时候决定写这篇博客,好吧不啰嗦了 ​ 继续上一篇文章,后我有个问题(上文:&qu ...

  7. 最全的ORACLE-SQL笔记

    -- 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott account unloc ...

  8. Mysql中较为复杂的分组统计去重复值

    这是我的代码: 前提是做了一个view:att_sumbase 首先分开统计每天的中午.下午饭点人数,这时需要分别去除中午和下午重复打卡的人.用了记录集的交,嵌套select的知识. 注意不能直接使用 ...

  9. django源码分析

    原文网址 https://www.jianshu.com/p/17d78b52c732?utm_campaign=maleskine&utm_content=note&utm_medi ...

随机推荐

  1. Python-2.7 配置tab自动补全功能

    作者博文地址:http://www.cnblogs.com/spiritman/ 之前一直使用shell编程,习惯了shell的 tab 自动补全功能,而Python的命令行却不支持 tab 自动补全 ...

  2. mysql基础知识大全

    前言:本文主要为mysql基础知识的大总结,mysql的基础知识很多,这里作简单概括性的介绍,具体的细节还是需要自行搜索.当然本文还有很多遗漏的地方,后续会慢慢补充完善. 数据库和数据库软件 数据库是 ...

  3. 2018软工实践—Alpha冲刺(5)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助测试的进行 测试项目运行的服务器环境 ...

  4. SSD/Memory技术学习拼图

    "打酱油"解读SLC缓存新技术[http://www.pceva.com.cn/article/3612-1.html] 固态硬盘主控将消亡?未来高性能固态硬盘长这样[http:/ ...

  5. lintcode-206-区间求和 I

    206-区间求和 I 给定一个整数数组(下标由 0 到 n-1,其中 n 表示数组的规模),以及一个查询列表.每一个查询列表有两个整数 [start, end] . 对于每个查询,计算出数组中从下标 ...

  6. iOS-封装UIPickerView

    创建类WJPickerView继承与UIView ProvinceModel是省市的model,包含属性 @property (nonatomic, strong) NSString *provinc ...

  7. "firstday"-软件工程

    阅读以下文章 http://www.thea.cn/news/terminal/9/9389.html    http://www.shzhidao.cn/system/2015/09/22/0102 ...

  8. IDEA配置Java Web项目

    IDEA部署maven tomcat的java web项目的关键配置:

  9. mysql(六)索引的数据结构

    先做抽象定义如下: 定义一条数据记录为一个二元组[key, data],key为记录的键值,对于不同的数据记录,key是互不相同的:data为数据记录除key外的数据. B-tree的特点: d为大于 ...

  10. 第79天:jQuery事件总结(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 一.合成事件 jQuery有两个合成事件——hove ...