IO多路复用select/poll/epoll详解以及在Python中的应用
IO multiplexing(IO多路复用)
IO多路复用,有些地方称之为event driven IO(事件驱动IO)。
它的好处在于单个进程可以处理多个网络IO请求。select/epoll这两个是函数,它会不断轮询所有的socket,直到某个socket就绪有数据可达,就会通知用户进程,当用户进程调用了select函数,select是一个阻塞方法,会把进程阻塞住,同时会监听所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用readRecv操作,将数据从内核拷贝到用户进程。

select虽然是阻塞的,但是它的优势在于它可以用一个进程处理多个连接,这个利用非阻塞的轮询方式是无法实现的,当连接数增多时优势就明显,而对于单个连接则跟同步IO区别不大甚至性能还要更低。
select,poll,epoll都是IO多路复用的机制,IO多路复用就是通过机制用一个进程监视多个描述符,一旦某个描述符就绪(可读或者可写或者异常),能够通知进程进行响应的操作。但是select,poll,epoll本质上是同步IO,因为他们都需要在读写事件就绪后自己负责读写,这个过程是阻塞的。
下面用Python的socket编程模拟IO多路复用(IO多路复用+回调+事件循环)
class Fetcher:
def connected(self, key):
selector.unregister(key.fd)
self.con.send('GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n'.format(self.path,self.host).encode('utf-8'))
selector.register(self.con.fileno(), EVENT_READ, self.read)
def read(self, key):
d = self.con.recv(1024)
if d:
print(d)
self.data += d
else:
selector.unregister(key.fd)
self.data = self.data.decode('utf-8')
html_data = self.data.split('\r\n\r\n')[1]
print(html_data)
self.con.close()
def get_url(self, url):
...
self.con = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.con.setblocking(False)
#设置非阻塞
try:
self.con.connect((self.host, 80))
except BlockingIOError as e:
pass
selector.register(self.con.fileno(), EVENT_WRITE, self.connected)
过程:发送一个socket请求设置为非阻塞,在select函数中注册事件,self.con.fileno表示当前连接在进程中的描述符,EVENT_WRITE表示socket准备是否就绪,self.connected为回调函数,准备完成后就调用。selector.unregister(key.fd)取消注册,发送HTTP请求,再调用selector.register(self.con.fileno(), EVENT_READ, self.read)注册,若当前请求内容可读,则调用read回调函数读取出响应内容。
注明:在windows下会调用select函数,而在linux/unix下则会调用epoll函数
完整代码如下:
import socket
from urllib.parse import urlparse
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE
selector = DefaultSelector()
class Fetcher:
def connected(self, key):
selector.unregister(key.fd)
self.con.send('GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n'.format(self.path,self.host).encode('utf-8'))
selector.register(self.con.fileno(), EVENT_READ, self.read)
def read(self, key):
d = self.con.recv(1024)
if d:
print(d)
self.data += d
else:
selector.unregister(key.fd)
self.data = self.data.decode('utf-8')
html_data = self.data.split('\r\n\r\n')[1]
print(html_data)
self.con.close()
def get_url(self, url):
url = urlparse(url)
self.host = url.netloc
self.path = url.path
self.data = b''
if self.path == "":
self.path = '/'
self.con = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.con.setblocking(False)
try:
self.con.connect((self.host, 80))
except BlockingIOError as e:
pass
#注册
selector.register(self.con.fileno(), EVENT_WRITE, self.connected)
def loop():
while True:
ready = selector.select()
for key, mask in ready:
callback = key.data
callback(key)
if __name__ == '__main__':
fetcher = Fetcher()
fetcher.get_url('http://www.baidu.com')
loop()
IO多路复用select/poll/epoll详解以及在Python中的应用的更多相关文章
- Linux IO模式以及select poll epoll详解
一 背景 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network ...
- 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】
下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程
1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...
- 最快理解 - IO多路复用:select / poll / epoll 的区别.
目录 第一个解决方案(多线程) 第二个解决方案(select) 第三个解决方案(poll) 最终解决方案(epoll) 客栈遇到的问题 从开始学习编程后,我就想开一个 Hello World 餐厅,由 ...
- Linux IO多路复用 select/poll/epoll
Select -- synchronius I/O multiplexing select, FS_SET,FD_CLR,FD_ISSET,FD_ZERO #include <sys/time. ...
- python网络编程——IO多路复用select/poll/epoll的使用
转载博客: http://www.haiyun.me/archives/1056.html http://www.cnblogs.com/coser/archive/2012/01/06/231521 ...
- Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...
- 【操作系统】I/O多路复用 select poll epoll
@ 目录 I/O模式 I/O多路复用 select poll epoll 事件触发模式 I/O模式 阻塞I/O 非阻塞I/O I/O多路复用 信号驱动I/O 异步I/O I/O多路复用 I/O 多路复 ...
- 多路复用select poll epoll
I/O 多路复用之select.poll.epoll详解 select,poll,epoll都是IO多路复用的机制.I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般 ...
随机推荐
- C#中Main函数为什么要static
假设没有static关键字,那意味着需要用生成一个实例后才可以调用这个Main方法,而Main方法是程序入口点,你没有进入Main方法,自然无法生成一个实例,既然没有实例,那就无法调用Main函数,岂 ...
- Android Interpolator(插值器)
1.概述 插值器定义如何计算动画中的特定值作为时间的函数.例如,指定动画在整个动画中线性发生,这意味着动画在整个时间内均匀移动,或者指定动画以使用非线性时间,例如,在开始或结束时使用加速或减速动画. ...
- php面向对象高级-魔术方法与迭代器
1,魔术方法__set与__get, __call >这些魔术方法,将在相关的属性或者方法不存在时调用 >函数原型 .function __set( $property, $value ) ...
- div阴影
.box-shadow{ //Firefox4.0- -moz-box-shadow:投影方式 X轴偏移量 Y轴偏移量阴影模糊半径 阴影扩展半径 阴影颜色; //Safariand Google ch ...
- ERP、CRM、CMS
ERP: 全称:Enterprise Resource Planning 解释:企业资源计划. ERP 是一种主要面向制造行业进行物质资源.资金资源和信息资源集成一体化管理的企业信息管理系统.ERP ...
- JS 获取css transform中的值
可以参考这位博主的文章https://www.cnblogs.com/zhenwoo/p/4993780.html 不想看直接想看怎么解决的看这: var translates= document.d ...
- BZOJ2208: [Jsoi2010]连通数(tarjan bitset floyd)
题意 题目链接 Sol 数据水的一批,\(O(n^3)\)暴力可过 实际上只要bitset优化一下floyd复杂度就是对的了(\(O(\frac{n^3}{32})\)) 还可以缩点之后bitset维 ...
- 前后端分离(手) -- mock.js
前言: 本篇博文昨天七夕写的,一天下来被虐得体无完肤,苦逼的单身狗只能学习,对!我爱学习,关掉朋友圈,并写了一篇博文发泄发泄.这次写mock.js的使用,能使前后端分离,分离,分离,重要的是说三遍. ...
- Android 外部启动activity,自定义action,action常量大全
从任意app,启动另外一个app的activity: 1. Intent i = new Intent(); ComponentName cn = new ComponentN ...
- 最近见到一个用react native实现的标尺动画,不知道如何实现 帖两张图(新知食App)
很恶心,这款App的标尺没有做兼容,我在模拟上看不到效果,无法说明我想做出的东西的效果,无奈粘一张图吧! 就是这么一个屌样子,如何实现?