首页 > 编程语言 >python IO多路复用理解记录

python IO多路复用理解记录

时间:2023-05-06 14:45:23浏览次数:39  
标签:socket 多路复用 epoll python server 描述符 IO poll select

一、 简述:

1什么是多路 I/O 复用机制

  • Python 中的多路 I/O 复用机制是一种高效的编程技巧,用于同时监视多个文件描述符是否有可读、可写或错误事件,并在这些描述符中任意一个或多个有事件发生时立即进行响应。

2 使用多路I/O 复用机制的目的

  • 同时处理多个连接时提高网络I/O效率,从而提高程序的整体性能。

 3 适用场景

  • 各种 I/O 密集型应用程序的编程。

二、常用机制

Python,常用多路I/O复用机制可供选择,包括selectpollepollasyncio等。这些机制都提供了一种方式来同时监视多个I/O事件,并且可以有效地处理并发的I/O操作。

  • selectselect是最基本和最常见的多路I/O复用机制之一,适用于大多数Unix平台。它通过调用select.select()函数来等待一组文件描述符上的事件,并返回已就绪的文件描述符列表。select的一个缺点是它对于大量的文件描述符会有性能问题。

  • pollpoll是类似于select的多路I/O复用机制,但在处理大量文件描述符时性能更好。它通过调用select.poll()创建一个poll对象,并使用register()方法注册文件描述符及其感兴趣的事件。然后,使用poll()方法等待事件的发生,并返回就绪的文件描述符列表。

  • epollepoll是在Linux上使用的高性能多路I/O复用机制。它使用内核事件通知机制来实现高效的I/O事件监视,适用于大规模的并发连接。epoll提供了select.epoll()函数来创建一个epoll对象,并使用register()方法注册文件描述符及其感兴趣的事件。然后,使用poll()方法等待事件的发生,并返回就绪的文件描述符列表。

  • asyncioasyncio是Python标准库中提供的异步I/O框架。它基于协程和事件循环的概念,提供了高层次的抽象来处理异步I/O操作。使用asyncio,可以通过asyncio.select()函数等待多个异步I/O操作,并在事件就绪时执行相应的回调函数。asyncio对于构建高性能的异步网络应用非常有用。

二、示列:

#1 select示例:
import select
import socket

# 创建套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8080))
server_socket.listen(5)
inputs = [server_socket]

while True:
    """
    参数说明:
    rlist(Readable List):包含需要监视可读事件的文件描述符的列表。当列表中的文件描述符准备好从其读取数据时,select 函数将返回这些文件描述符。
    wlist(Writable List):包含需要监视可写事件的文件描述符的列表。当列表中的文件描述符准备好向其写入数据时,select 函数将返回这些文件描述符。
    xlist(Exceptional List):包含需要监视异常事件的文件描述符的列表。当列表中的文件描述符发生异常情况时,如连接错误或带外数据,select 函数将返回这些文件描述符。
    """
readable, writable, exceptional = select.select(inputs, [], []) for sock in readable: if sock is server_socket: # 新的连接 client_socket, client_address = server_socket.accept() inputs.append(client_socket) else: # 可读数据 data = sock.recv(1024) if data: # 处理数据 print(data.decode()) else: # 客户端关闭连接 inputs.remove(sock) sock.close()
# 2poll示例: import select import socket # 创建套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 8080)) server_socket.listen(5) poller = select.poll() poller.register(server_socket, select.POLLIN) while True: events = poller.poll() for fd, event in events: if fd == server_socket.fileno(): # 新的连接 client_socket, client_address = server_socket.accept() # 参数为可迭代的对象 poller.register(client_socket, select.POLLIN) else: # 可读数据 sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) data = sock.recv(1024) if data: # 处理数据 print(data.decode()) else: # 客户端关闭连接 poller.unregister(fd) sock.close()

#3 epoll示例: import select import socket # 创建套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 8080)) server_socket.listen(5) epoller = select.epoll() epoller.register(server_socket.fileno(), select.EPOLLIN) while True: events = epoller.poll() for fd, event in events: if fd == server_socket.fileno(): # 新的连接 client_socket, client_address = server_socket.accept() client_socket.setblocking(0) ''' 常用的events标志有: EPOLLIN:表示可读事件 EPOLLOUT:表示可写事件 EPOLLRDHUP:表示对端连接关闭 EPOLLERR:表示错误事件 EPOLLHUP:表示挂起事件 ''' epoller.register(client_socket.fileno(), select.EPOLLIN) else: # 可读数据 sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) data = sock.recv(1024) if data: # 处理数据 print(data.decode()) else: # 客户端关闭连接 epoller.unregister(fd) sock.close()

#4 asyncio示例: import asyncio async def handle_client(reader, writer): data = await reader.read(1024) message = data.decode() addr = writer.get_extra_info('peername') print(f"Received {message} from {addr}") # 响应客户端 response = "Hello, client!" writer.write(response.encode()) await writer.drain() writer.close() async def main(): server = await asyncio.start_server( handle_client, 'localhost', 8080) addr = server.sockets[0].getsockname() print(f'Serving on {addr}') async with server: await server.serve_forever() asyncio.run(main())

三、区别 

  主要对select、poll、epoll 进行比较

  1. 适用系统不同:
  • select、poll:在多个操作系统上均可使用;
  • epoll:仅能在 Linux 系统上使用。
  1. 监听数量不同:
  • select:最多支持 1024 个文件描述符的监听;
  • poll:支持数目比 select 多,但仍有限制;
  • epoll:支持的数量没有明确的上限。
  1. 内部实现不同:
  • select、poll 通过遍历监听的所有文件描述符来检测是否有 I/O 事件发生,效率较低;
  • epoll 利用 epoll_ctl 系统调用来维护和更新事件列表,通过 epoll_wait 来通知进程哪些文件有读写操作的事件发生,效率更高。
  1. 事件注册方式不同:select、poll 的FD集合是一个静态的数据结构,因此每次注册事件都需要构建一个新的FD集合,效率较低;
  • epoll 采用基于事件的就绪通知方式,采用 epoll_ctl() 函数向内核注册感兴趣的事件类别。

         5.asyncio与其他三种的区别:

  • 是Python标准库提供的异步I/O框架。
  • 基于协程和事件循环的概念,提供了高层次的抽象来处理异步I/O操作。
  • 使用asyncio.select()函数等待多个异步I/O操作,并在事件就绪时执行相应的回调函数。
  • 强调基于事件驱动的编程模型,可以方便地编写异步代码。
 这些多路I/O复用机制在实现方式、可移植性和性能方面有所差异。选择适当的机制取决于应用程序的需求、目标平台和预期的并发规模。

标签:socket,多路复用,epoll,python,server,描述符,IO,poll,select
From: https://www.cnblogs.com/wxbn/p/17377255.html

相关文章

  • Controllable Guarantees for Fair Outcomes via Contrastive Information Estimation
    目录概符合说明Motivation优化目标代码GuptaU.,FerberA.M.,DilkinaB.andSteegG.V.Controllableguaranteesforfairoutcomesviacontrastiveinformationestimation.AAAI,2021.概本文提出了一种类似InformationBottleneck的方式用于保证两个群体的fairn......
  • 一统天下 flutter - 存储: shared_preferences - 用于操作 android 的 SharedPreferen
    源码https://github.com/webabcd/flutter_demo作者webabcd一统天下flutter-存储:shared_preferences-用于操作android的SharedPreferences,ios的NSUserDefaults,web的LocalStorage示例如下:lib\storage\shared_preferences.dart/**shared_preferences......
  • react-navigation 页面跳转
    使用react-navigation在进行页面跳转的时候,遇到些问题,现在来总结下,主要是web和android的差异react-navigation页面跳转方法navigationnavigate-转到另一个屏幕,找出需要采取的操作replace-用新屏幕替换当前屏幕push-将新屏幕推到堆栈上pop-回到堆栈中popToTo......
  • Module build failed (from ./node_modules/css-loader/dist/cjs.js): TypeError: thi
    Modulebuildfailed(from./node_modules/css-loader/dist/cjs.js):TypeError:this.getOptionsisnotafunctionModulebuildfailed(from./node_modules/css-loader/dist/cjs.js):TypeError:this.getOptionsisnotafunction 用了各种办法,没有解决问题,直接把node_m......
  • 《c++徒步》IO篇
    iostreamcincout参考链接:https://www.runoob.com/cplusplus/cpp-basic-input-output.html标准输出#include<iostream>usingnamespacestd;intmain(){charstr[]="HelloC++";cout<<"Valueofstris:"<<str&l......
  • Struts2----中使用ValueStack、ActionContext、ServletContext、request、session等
     声明:本文参考Struts2版本为2.3.1.2,内容仅供参考,限于笔者水平有限,难免有所疏漏,望您能友善指出。本文发表于ITEYE,谢绝转载。1.ValueStack  ValueStack在中文版的《Struts2深入浅出》一书中译作“值栈”。其本身数据结构是一个栈,使用者可以把一些对象(又称作bean)存入值栈中,然后......
  • AndroidStudio插件GsonFormat快速实现JavaBean
    安装方法一:1.AndroidstudioFile->Settings..->Plugins–>Browserepositores..搜索GsonFormat2.安装插件,重启androidstudio方法二:1.下载GsonFormat.jar;2.AndroidstudioFile->Settings..->Plugins–>installpluginfromdisk..导入下载GsonFormat.jar3.重启android......
  • Could not create ActionMapper: WebWork will *not* work!
    CouldnotcreateActionMapper:WebWorkwill*not*work!解决方法:将webwork.properties的webwork.objectFactory=springwebwork.objectFactory.spring.autoWire=name 两行去掉就可以了......
  • application/x-www-form-urlencoded & multipart/form-data & text/plain
    FORM元素的enctype属性指定了表单数据向服务器提交时所采用的编码类型  我们知道在通过POST方式向服务器发送AJAX请求时最好要通过设置请求头来指定为application/x-www-form-urlencoded编码类型。知道通过表单上传文件时必须指定编码类型为"multipart/form-data"。而text/plain......
  • python中的报错:dictionary changed size during iteration
    该报错是一个python中常见的错误,通常在使用for循环迭代字典时删除其中的元素时出现。这个问题的根本原因在于迭代字典的同时修改了它,导致字典的大小发生了变化。如下面的例子,就会报错:d={"a":1,"b":2,"c':3}fork,vind.items():ifv==2:deld[k]上述......