select网络模型知识总结
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网络模型知识总结的更多相关文章
- linux select 网络模型
io模型: 同步IO: 阻塞形式,非阻塞形式(轮询).信号驱动IO.IO复用(select, poll, epoll): 异步io:aio_read() 典型场景: 1.客户端处理多种IO------ ...
- python 3下基于select模型的事件驱动机制程序
它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程.它的流程如图: 当用户进程调用了select,那么整个 ...
- EasyDarwin开源流媒体server将select改为epoll的方法
本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听全部网络读写事件.Even ...
- EasyDarwin开源流媒体服务器将select改为epoll的方法
本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听所有网络读写事件,Even ...
- 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能
经过春节前后将近2个月的开发和稳定调试.测试,EasyDarwin开源流媒体服务器终于成功将底层select网络模型修改优化成epoll网络模型,将EasyDarwin流媒体服务器在网络处理的效率上提 ...
- Django源码分析之启动wsgi发生的事
前言 好多人对技术的理解都停留在懂得使用即可,因而只会用而不会灵活用,俗话说好奇害死猫,不然我也不会在凌晨1.48的时候决定写这篇博客,好吧不啰嗦了 继续上一篇文章,后我有个问题(上文:&qu ...
- 最全的ORACLE-SQL笔记
-- 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott account unloc ...
- Mysql中较为复杂的分组统计去重复值
这是我的代码: 前提是做了一个view:att_sumbase 首先分开统计每天的中午.下午饭点人数,这时需要分别去除中午和下午重复打卡的人.用了记录集的交,嵌套select的知识. 注意不能直接使用 ...
- django源码分析
原文网址 https://www.jianshu.com/p/17d78b52c732?utm_campaign=maleskine&utm_content=note&utm_medi ...
随机推荐
- JAVA学习笔记--组合与继承
JAVA一个很重要的功能就是代码的可复用性,代码复用可以大大提升编程效率.这里主要介绍两种代码复用方式:组合和继承. 一.组合 组合比较直观,只需在新的类中产生现有类的对象,新的类由现有类的对象组成, ...
- DX孟虎点评新兴市场:巴西俄罗斯火爆背后
[亿邦动力网讯]4月3日消息,在第九届中国中小企业电子商务大会暨2014中国(河南)跨境贸易电子商务峰会上,DX公司CEO孟虎对新兴市场做了详细的分析,指出在当今的跨境电商环境下,北美.西欧作为电商成 ...
- Alpha阶段事后诸葛亮会议记录
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2324 组名:可以低头,但没必要 组长:付佳 组员:张俊余 李文涛 孙 ...
- Team Work总结 && OPP课程总结
团队作业总结 工作总结 本次大作业我在团队内的工作是:根据框架构建实现建筑类的功能,包括防御塔.水晶.泉水等建筑.根据架构框架以及结合各建筑的特点,利用继承和多态很快速的解决了一些基本的问题.然而在实 ...
- lintcode-223-回文链表
223-回文链表 设计一种方式检查一个链表是否为回文链表. 样例 1->2->1 就是一个回文链表. 挑战 O(n)的时间和O(1)的额外空间. 标签 链表 思路 找到链表中点后,翻转链表 ...
- Tomcat配置 —— server.xml
Tomcat的核心组件是servlet容器. Tomcat各个组件之间的嵌套关系 server.xml配置如下: <Server port="8005" shutdown=& ...
- 把a文件删除b文件中的相同的行
grep -vxFf b.txt a.txt > newa.txt 更好的方法是 comm - - b.txt a.txt > newa.txt 来自Tool in unix to sub ...
- Struts2(五)
以下内容是基于导入struts2-2.3.32.jar包来讲的 1.文件上传 A.单文件上传 <body> <form action="${pageContext.requ ...
- python/django将mysql查询结果转换为字典组
使用python查询mysql数据库的时候,默认查询结果没有返回表字段名称,不方便使用.为了方便使用一般会选择将查询结果加上字段名称以字典组的方式返回查询结果. 实现如下: def dict_fetc ...
- 免费各种查询API接口
快递查询 http://www.kuaidi100.com/query?type=quanfengkuaidi&postid=390011492112 (PS:快递公司编码:申通"s ...