epoll——IO多路复用选择器
上上篇博客讲的套接字,由于其阻塞性而导致一个服务端同一时间只能与一个客户端连接。基于这个缺点,在上篇博客我们将其设置为非阻塞实现了一个服务端同一时间可以与多个客户端相连,即实现了并发,但其同样留下了一个缺点:CPU的利用率低。这一篇博客是基于这个缺点再进一步进行改善,即实现并发,又提高CPU的利用率。
什么是epoll?
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。epoll是当前Linux下效率最高的IO多路复用技术,值得一提的是,epoll是一个惰性的事件回调,操作系统仅仅起到监听作用,对于是否有连接请求发过来了,它需要用户自己去查询。
IO多路复用技术
在之前,我们一直都是利用监听套接字去接收客户端的连接请求,如果连接请求一直没来,就会一直处于无用的循环。但如果利用epoll的IO多路复用技术,我们就可以将socket的监听工作交给操作系统,而其本身可以去做其他的事情。在python中我们要用到的模块是selectors,selectors模块是在python3.4版本中引进的,它封装了IO多路复用中的select和epoll,能够更快,更方便的实现多并发效果。抛开套接字,它的大体流程如下:
- 实例化一个epoll选择器
- 对epoll选择器进行注册,从而起到让操作系统去监听,参数有套接字、事件、回调函数。它会把刚生成的sock连接对象注册到select连接列表中,并交给accept函数处理 。
- 对select进行查找,若查找为空,默认是阻塞,否则返回活动的连接列表。
- 调用回调函数
- 注销选择器
selectors模块的官方文档
事件的类型:
1.可读事件select.EVENT_READ 2.可写事件select.EVENT_WRITE
服务端代码:
import socket
import selectors
def acce(server):#对客户端的请求建立连接
a, b = server.accept()
select.register(a,selectors.EVENT_READ,recv)#有信息发过来才会触发事件
def recv(a):#对已建立连接的客户端进行收发信息
date = a.recv(1024)
if date:
print("已收到信息-->{}".format(date.decode()))
a.send(date)
else:
select.unregister(a)
a.close()
server = socket.socket()
server.bind(('127.0.0.5',8520))
server.listen(50)
select = selectors.DefaultSelector()#selectors模块默认会用epoll,如果你的系统中没有epoll(比如windows)则会自动使用select
select.register(server,selectors.EVENT_READ,acce)#有连接请求过来才会触发事件,第一个参数是套接字,第二个是事件类型,第三个是回调函数。
while True:
events = select.select()#触发的事件需要自己的查询, 默认是阻塞,有活动连接就返回活动的连接列表
for i,j in events:
callback = i.data #回调函数
sock = i.fileobj #套接字
callback(sock)#调用回调函数
客户端代码
import socket
client = socket.socket()
client.connect(('127.0.0.5',8520))
mess = input('--->').encode()
client.send(mess)
print("已收到回应-->{}".format(client.recv(1024)))
client.close()
上述服务端代码中,epoll选择器注册后对象结构如下图,只有请求连接过来时才会触发到的这个事件,但事件本身需要自己查询。
事件被触发后自己手动查询,特别的是如果没有事件,即没有客户端的请求连接,这里会有阻塞。当有事件时,他会返回一个列表的二元组。
这个事件中被我们用到的信息有两个,一个是套接字,一个是回调函数。可以将其直接取出来或如上图代码一样先拆包再取出来。下图是直接取出来。
总结:上述代码的效果也实现了并发,可以让一个服务端同时与多个客户端相连,相对于非阻塞套接字实现的并发,这里提高了CPU的利用率,因为这里是让操作系统充当监听工作,当选择器查找为空时,选择器会因为阻塞停止工作,若不为空,它会调用回调函数进行下一步工作。对于收发信息,它也是注册了一个事件,从而交给操作系统去监听,不需要对等连接套接字一直循环去监视。
epoll——IO多路复用选择器的更多相关文章
- epoll—IO多路复用
1.在socket.listen()后创一个epoll对象 epoll = select.epoll() 2.将server_socket注册到epoll中 epoll.regist ...
- epoll IO多路复用(异步阻塞AIO)
epoll的异步阻塞(AIO): 用户线程创建epoll后,其实是内核线程负责扫描 fd 列表(在网络服务器上可以是socket,socket在创建后返回的也是文件描述符),并填充事件链表.但是,并不 ...
- 【python】-- IO多路复用(select、poll、epoll)介绍及实现
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
- IO多路复用(select、poll、epoll)介绍及select、epoll的实现
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
- 11 非阻塞套接字与IO多路复用(进阶)
1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建 ...
- 利用IO多路复用,使用linux下的EpollSelector实现并发服务器
import socket import selectors # IO多路复用选择器的模块 # 实例化一个和epoll通信的选择器 epoll_selector = selectors.EpollSe ...
- 异步、非阻塞和IO多路复用总结
Nginx是并发处理框架的代表者,很多后台业务都会放在Nginx容器中运行,以实现高吞吐,而Nginx能够支持高并发也是由于使用了异步非阻塞处理模型,本文将用通俗的话讲解异步.同步.阻塞.非阻塞的区别 ...
- 网络编程基础【day10】:IO多路复用
这些名词比较绕口,理解涵义就好.一个epoll场景:一个酒吧服务员(一个线程),前面趴了一群醉汉,突然一个吼一声“倒酒”(事件),你小跑过去给他倒一杯,然后随他去吧,突然又一个要倒酒,你又过去倒上,就 ...
- Python全栈开发-Day10-进程/协程/异步IO/IO多路复用
本节内容 多进程multiprocessing 进程间的通讯 协程 论事件驱动与异步IO Select\Poll\Epoll——IO多路复用 1.多进程multiprocessing Python ...
随机推荐
- 吴裕雄--天生自然C++语言学习笔记:C++ STL 教程
C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表.队列.栈. C++ 标准模板库的核心包括以 ...
- robotframework+selenium2Library怎样不用手动关掉代理
每次跑脚本,启动浏览器都要手动关掉代理,太费劲了,发现最简单的办法就是在局域网设置里面勾上跳过本地地址的代理服务器,并且在例外里写上127.0.0.1 就这么简单有没有??
- C语言拾遗——inttypes.h
今天偶然间看到这个头文件inttypes,好奇有什么用,去找度娘玩了一波,发现这头文件挺有意思的. 这个头文件适配于C99标准,它提供整数输入的各种进制转换的宏,这是在Ubuntu上扣下来的代码(wi ...
- Egret - EUI - 隐藏滚动条
<e:Skin> <e:VScrollBar autoVisibility="false" visible="false"/> < ...
- jquery 获取同级元素
$(".userinfo-three:eq(0)").css({ "width": winWidth * 300 / 1080, ...
- C++基础--智能指针
智能指针其实也不是完全的指针,应该说是像指针一样的类对象,智能指针通常有指针的功能,当然同时也包含了一些额外的功能.目前比较常见的智能指针有auto_ptr.unique_ptr和shared_ptr ...
- 安装swoole redis异步 hiredis swoole扩展加载失败 或者不显示问题 解决办法
当前办法仅供参考 贴上报错 找了好久 根据网上办法也试了 没解决 最后 仔细读问题 觉得可能是 hiredis路径问题 终于解决了 解决办法: 进入你的安装包目录然后执行下面 mkdir /usr/l ...
- Vue.js(2)- 过滤器
概念:过滤器本质上就是一个函数,可被用作一些常见的文本格式化. 过滤器只可以用在两个地方:mustache 插值表达式和 v-bind 表达式. 过滤器应该被添加在 JavaScript 表达式的尾部 ...
- 201812-1 小明上学 Java
思路: 上学这个题和放学有区别,上学是小明每到一个路口的情况,是实时更新的.不是只有出发时间,那样就比较复杂了. 这个题需要注意:黄灯之后要等红灯,想一下交通规则. import java.util. ...
- Vue 指令 v-text v-html
有三个指令达到的效果是一样的 {{JS表达式}} 差值表达式 v-text="JS表达式" v-html="JS表达式" //会自动解析tag js表达式 ...