上上篇博客讲的套接字,由于其阻塞性而导致一个服务端同一时间只能与一个客户端连接。基于这个缺点,在上篇博客我们将其设置为非阻塞实现了一个服务端同一时间可以与多个客户端相连,即实现了并发,但其同样留下了一个缺点: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,能够更快,更方便的实现多并发效果。抛开套接字,它的大体流程如下:

  1. 实例化一个epoll选择器
  2. 对epoll选择器进行注册,从而起到让操作系统去监听,参数有套接字、事件、回调函数。它会把刚生成的sock连接对象注册到select连接列表中,并交给accept函数处理 。
  3. 对select进行查找,若查找为空,默认是阻塞,否则返回活动的连接列表。
  4. 调用回调函数
  5. 注销选择器

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多路复用选择器的更多相关文章

  1. epoll—IO多路复用

    1.在socket.listen()后创一个epoll对象   epoll = select.epoll() 2.将server_socket注册到epoll中        epoll.regist ...

  2. epoll IO多路复用(异步阻塞AIO)

    epoll的异步阻塞(AIO): 用户线程创建epoll后,其实是内核线程负责扫描 fd 列表(在网络服务器上可以是socket,socket在创建后返回的也是文件描述符),并填充事件链表.但是,并不 ...

  3. 【python】-- IO多路复用(select、poll、epoll)介绍及实现

    IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...

  4. IO多路复用(select、poll、epoll)介绍及select、epoll的实现

    IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...

  5. 11 非阻塞套接字与IO多路复用(进阶)

    1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建 ...

  6. 利用IO多路复用,使用linux下的EpollSelector实现并发服务器

    import socket import selectors # IO多路复用选择器的模块 # 实例化一个和epoll通信的选择器 epoll_selector = selectors.EpollSe ...

  7. 异步、非阻塞和IO多路复用总结

    Nginx是并发处理框架的代表者,很多后台业务都会放在Nginx容器中运行,以实现高吞吐,而Nginx能够支持高并发也是由于使用了异步非阻塞处理模型,本文将用通俗的话讲解异步.同步.阻塞.非阻塞的区别 ...

  8. 网络编程基础【day10】:IO多路复用

    这些名词比较绕口,理解涵义就好.一个epoll场景:一个酒吧服务员(一个线程),前面趴了一群醉汉,突然一个吼一声“倒酒”(事件),你小跑过去给他倒一杯,然后随他去吧,突然又一个要倒酒,你又过去倒上,就 ...

  9. Python全栈开发-Day10-进程/协程/异步IO/IO多路复用

    本节内容 多进程multiprocessing 进程间的通讯 协程 论事件驱动与异步IO Select\Poll\Epoll——IO多路复用   1.多进程multiprocessing Python ...

随机推荐

  1. java IO 流关系图谱

    学习io流最好明白其之间的 关联与转换关系 ,以下是笔者所划得 关系图谱,大框包含小框 ,小框是大框内的 请求参数,箭头是继承或实现. 清晰了其关联与包含关系后我们便很容易在现实中结合使用了 . 这是 ...

  2. SpringBoot实现OAuth2认证服务器

    一.最简单认证服务器 1. pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <a ...

  3. linux shell的创建与启动

    1.创建shell脚本,输入linux命令: touch my.sh 2.编辑shell脚本,输入linux命令: vi my.sh 3.在shell脚本进行编辑:顺便记一次Jenkins的自动启动的 ...

  4. 2. Jetson TX2--python3下编译安装opencv3.4

    https://cloud.tencent.com/developer/article/1327273 jetpack3.2自带了opencv3.3,但是只提供了python2.7的编译版本,所以也只 ...

  5. MVC MVP MVVM 简述

    MVC 通过代理或者通知传递数据. MVP 通过P绑定model和view解耦. MVVM 通过V绑定VM(监听VM属性的变化.方法传递(改变自身被监听属性)) VM绑定model设置自身属性.

  6. 原生js完成打地鼠小游戏

    :这是首页,有简单模式和地狱模式两种模式进行选择 这是选择完模式之后的游戏界面:30秒一局游戏倒计时,每打中一只老鼠加一分,没砸中减一分,没砸不加不减 首先准备几张图片 html代码: <!-- ...

  7. mysql+MHA高可用 (一主双从)

    1.准备三台服务器 10.0.0.12 10.0.0.13 10.0.0.14 2.在三台服务器上执行操作 时间同步 [root@ c7m01 ~]# echo "*/5* * * * /u ...

  8. 二、CI框架之MCV模型

    一.关于MCV,大概就是下图所示: 模型(model)-视图(view)-控制器(controller) M用来处理数据库,V用来显示界面,C用来控制 二.对应到CI的源码,对应的是这3个目录 不忘初 ...

  9. UVA 11997 The K smallest Sums

    给出K*K的矩阵,每一行取一个数,构成K个数的和,总共有 k^k种可能,从中取出前k个最小的. 一开始犯了错,因为只要对每行排序,最小的必定是第一列的和,然后我当时就想着,逐步推进,每次将某行的那个数 ...

  10. HZNU-ACM寒假集训Day3小结 搜索

    简单搜索 1.DFS UVA 548 树 1.可以用数组方式实现二叉树,在申请结点时仍用“动态化静态”的思想,写newnode函数 2.给定二叉树的中序遍历和后序遍历,可以构造出这棵二叉树,方法是根据 ...