Python3之阻塞I/O,非阻塞I/O及I/O多路复用
来源:互联网 发布:金钻淘宝店有哪些 编辑:程序博客网 时间:2024/05/20 18:56
学习I/O模型,主要实现单线程条件下遇到I/O如何解决效率提升问题,也是协程要处理的问题。
阻塞I/O
我们在平时进行的socket编程时,链路循环中服务端接收链接,以及通信循环中服务端接收数据时,就是典型的阻塞I/O模型(主要服务端)。
代码示例
from socket import *s = socket(AF_INET, SOCK_STREAM)s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)s.bind(('127.0.0.1', 8080))s.listen(5)while 1: conn, addr = s.accept() while 1: try: data = conn.recv(1024) if not data:break conn.send(data.upper()) except Exception: break conn.close()s.close()
代码解析
- 主要两个地方处于阻塞状态:
- s.accept():该状态下server套接字等待操作系统把conn连接发给它,但是 操作系统一直在等待客户端链接,这个阶段处于阻塞状态。
- data = conn.recv(1024):该状态下conn套接字等待操作系统把数据拷贝给它,操作系统自己也需要等待客户端发送数据过来,这也使整个程序处于阻塞状态。
先贴张图:
IO发生时涉及的对象和步骤。对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。当一个read操作发生时,该操作会经历两个阶段,记住这两点很重要,因为这些IO模型的区别就是在两个阶段上各有不同的情况:
- 等待数据准备 (Waiting for the data to be ready)
- 将数据从内核拷贝到进程中(Copying the data from the kernel to the process)
非阻塞I/O
非阻塞I/O指在应用程序在操作系统wait for data阶段不需要等待,发一个系统调用给操作系统询问操作系统是否有数据,没有则会去干别的事情,有的话就接收一下数据。
代码示例
from socket import *s = socket(AF_INET, SOCK_STREAM)s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)s.setblocking(False)s.bind(('127.0.0.1', 8080))s.listen(5)conn_l = []del_conn = []while 1: try: conn, addr = s.accept() conn_l.append(conn) except Exception: for conn in conn_l: try: data = conn.recv(1024) conn.send(data.upper()) except BlockingIOError: pass except ConnectionResetError: #将客户端断开的链接剔除 for conn in del_conn: conn.close() del_conn.remove(conn) del_conn = []
代码解读
- 设置s.setblocking(False),套接字为非阻塞状态,这样server套接字不会等操作系统有数据才继续执行。
- 没有链接数据会抛一个异常,让程序继续向下执行,走的是通讯循环的逻辑。如果有数据则会将conn加到列表里面进行链接保存。
- 此种方式占用CPU过多,不推荐使用
I/O多路复用
代码示例
from select import selectfrom socket import *s = socket(AF_INET, SOCK_STREAM)s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)s.bind(('127.0.0.1', 8080))s.listen(5)select_l = [s, ]while 1: selected_l, _, _ = select(select_l, [], []) print(selected_l) for selected_item in selected_l: if selected_item == s: conn, addr = selected_item.accept() select_l.append(conn) else: data = selected_item.recv(1024) selected_item.send(data.upper())
注意问题
- select模块会自动过滤没有数据的套接字,有的话会将该套接字放入子集里面。
- 根据加入的套接字进行判断,是server套接字就取出链接和地址,是conn套接字就接收发送数据。
- select模块工作是基于列表去筛选哪个套接字有数据,效率较低,而且有套接字监控数量的限制,而poll只是对套接字监控数量做了扩展,没有实现高效筛选套接字的机制。
实现I/O多路复用的机制
select、poll、epoll
其中epoll克服了select和poll筛选效率低的问题,套接字数据有了就主动通知调用者进行处理,通过回调函数机制实现效率的大幅提升。但是只在linux平台下可以使用。这样selectors模块应运而生!它可以根据用户使用不同的平台来自动选择该使用select还是epoll,是不是很强大呢?!
待续~
阅读全文
1 0
- Python3之阻塞I/O,非阻塞I/O及I/O多路复用
- 非阻塞I/O
- 非阻塞I/O
- 非阻塞I/O
- 非阻塞文件I/O
- 非阻塞I/O简介
- 非阻塞I/O笔记
- 非阻塞I/O简介
- 83-非阻塞 I/O
- 非阻塞I/O和阻塞I/O
- 阻塞I/O和非阻塞I/O
- 阻塞I/O和非阻塞I/O
- 阻塞与非阻塞I/O
- 阻塞与非阻塞I/O
- 阻塞与非阻塞I/O
- 同步异步阻塞非阻塞I/O
- 阻塞与非阻塞I/O
- 阻塞与非阻塞I/O
- mysql-jdbc 6.0 serverTimezone参数详解
- 抓取360图片
- Java基础总结---IO流
- 俄国资安服务商发现可关闭英特尔管理引擎的方式
- VMware共享文件夹
- Python3之阻塞I/O,非阻塞I/O及I/O多路复用
- pdf在线预览
- HOSTOJ 1101: 那些四位数
- 阿里云视频技术专家柿蒂:视频AI in传媒九大业务场景解析
- 事件绑定
- Why is Java Future.get(timeout) & httpclient Not Reliable?
- 收获,不止SQL优化——抓住SQL的本质--第十一章
- char数组和char指针应该注意的
- 论oc函数内传双指针参数到另一函数