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 ...
随机推荐
- day06 再谈编码 and 作业讲解
1. 小数据池,(其他语言又叫常量池) id() 查看变量的内存地址 is和== is 判断内存地址是否一致 == 判断内容是否一致 小数据池的作用: 为了快速的创建字符串对象, 可以减少内存的浪费 ...
- UVA 11542 高斯消元
从数组中选择几个数,要求他们的乘积可以开平方,问有多少种方案. 先将单个数拆分成质因子,对于这个数而言,那些指数为奇数的质因子会使这个数无法被开平方. 所以我们需要选择一个对应质因子指数为奇数的元素, ...
- Qt应用程序重启
重启应用程序是一种常见的操作,在Qt中实现非常简单,需要用到QProcess类一个静态方法: // program, 要启动的程序名称 // arguments, 启动参数 bool startDet ...
- Django 使用 Celery 实现异步任务
对于网站来说,给用户一个较好的体验是很重要的事情,其中最重要的指标就是网站的浏览速度.因此服务端要从各个方面对网站性能进行优化,比如可采用CDN加载一些公共静态文件,如js和css:合并css或者js ...
- tomcat 最大并发连接数设置
转自: http://blog.csdn.net/qysh123/article/details/11678903 这是个很简单的问题,但是搜了一圈,发现大家都写错了.所以这里总结一下: 几乎所有的中 ...
- 获取秒级时间戳和毫秒级时间戳---基于python
获取秒级时间戳和毫秒级时间戳 import timeimport datetime t = time.time() print (t) #原始时间数据print (int(t)) #秒级时间戳prin ...
- IC设计前后端流程与EDA工具
IC前端设计(逻辑设计)和后端设计(物理设计)的区分: 以设计是否与工艺有关来区分二者:从设计程度上来讲,前端设计的结果就是得到了芯片的门级网表电路. 前端设计的流程及使用的EDA工具 1.架构的设计 ...
- 从一个app开始学iOS
在大学上了4年学,老师一直给灌输的思想就是,从细微处着手最后看到整体.举个网站的例子.第一个学期老师安排一门课java语言,期末考试就是考试java语言的知识.第二学期java web,第一次课配置j ...
- ASP.NET 文档
标题:ASP.NET 文档 地址:https://docs.microsoft.com/zh-cn/aspnet/index#pivot=core&panel=core_overview 标题 ...
- 【leetcode】300.Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...