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 ...
随机推荐
- springboot - 映射 /error 到自定义且实现了ErrorController的Controller
1.总览 2.代码 1).pom.xml <dependencies> <dependency> <groupId>org.springframework.boot ...
- getClass兼容ie
if (!document.getElementsByClassName) { document.getElementsByClassName = function(className, elemen ...
- 每天一点点之javascript(ES6) - Map对象
1.语法 键/值对的集合. mapObj = new Map() 注:集合中的键和值可以是任何类型.如果使用现有密钥向集合添加值,则新值会替换旧值. 2.属性下表列出了 Map 对象的属性和描述. 构 ...
- 用Python复制文件的9个方法(转)
转自:https://zhuanlan.zhihu.com/p/35725217 用Python复制文件的9个方法 Python 中有许多“开盖即食”的模块(比如 os,subprocess 和 sh ...
- CMenu类中禁用/变灰某一项
CMenu::EnableMenuItem 启用. 禁用,或变暗的菜单项. UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable); 参数 ...
- 十一、CI框架之输出用户IP地址
一.代码如下: 二.效果如下: 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.
- Swift字符串截取与Range使用
1.String.Index String.Index表示一个位置,使用String与String.Index可以获取该位置的Character let str = "123456789&q ...
- bugku-杂项 convert
打开题目文件,一大堆01码,用py转换成hex f=open("in.txt","r") print hex(int(str(f.read()),2)) f.c ...
- 使用Spring Data Mongodb的MongoRepository类进行增删改查
Spring Data Mongodb提供一套快捷操作 mongodb的方法,创建Dao,继承MongoRepository,并指定实体类型和主键类型. public interface CmsPag ...
- 简单makefile示例
Makefile cmd: - g++ 相信在linux下编程的没有不知道makefile的,刚开始学习linux平台下的东西,了解了下makefile的制作,觉得有点东西可以记录下. 下面是一个极其 ...