Python—I/O多路复用
一、I/O多路复用概念:
监听多个描述符的状态,如果描述符状态改变,则会被内核修改标志位,从而被进程获取进而进行读写操作
二、select,poll,epoll
select模块,提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用。
Windows Python:提供: select Mac Python:提供: select Linux Python:提供: select、poll、epollselect
在python中,select函数是一个对底层操作系统的直接访问的接口,它用来监控sockets、files和pipes,等待IO完成。当有可读、可写或是异常事件产生时,select可以很容易的监控到。
select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,这也是它所剩不多的优点之一。
select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏提升这一限制。
格式:rList,wList,eList = select.select(argv1,argv2,argv3,timeout)
参数:
argv1:监听序列中的句柄发生变化时,则获取发生变化的句柄添加到rList序列中
argv2:监听序列中含有句柄时,则将该序列中所有的句柄添加到wList序列中
argv3:监听序列中的句柄发生错误时,则将该发生错误的句柄添加到eList序列中
timeout:设置阻塞时间,如果不设置则默认一直阻塞
select 实例:
用select实现处理多个socket客户端请求
服务端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
ip_port = ('127.0.0.1',9999) sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建socket对象
sk.bind(ip_port) #绑定ip、端口
sk.listen(5) #监听
sk.setblocking(False) #不阻塞 inputs = [sk,]
outputs = []
while True:
rlist,wlist,eList = select.select(inputs,outputs,[],0.5)
print("inputs:",inputs) #查看inputs列表变化
print("rlist:",rlist) #查看rlist列表变化
for r in rlist:
if r == sk: #如果r是服务端
conn,address = r.accept()#
inputs.append(conn)
print (address)
else:
client_data = r.recv(1024)
if client_data: #如果有数据,返回数据
r.sendall(client_data)
else: #否则移除
inputs.remove(r)
客户端:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',9999) sk = socket.socket() #创建socket对象
sk.connect(ip_port) #通过ip和端口连接server端
while True:
inpu=input(">>:")
sk.sendall(bytes(inpu,"utf8")) #给server端发送信息 server_reply = sk.recv(1024) #接受消息
print (str(server_reply,"utf8")) #打印消息 sk.close() #关闭连接
过程:
启动服务端,这时select会一直监听服务端句柄,直到有客户端请求过来发生变化。
当客户端有新的连接请求过来时,select捕捉到服务端句柄发生变化,把变化的句柄加入到rlist,所以这时r == sk,接收这个链接并把句柄加入到inputs列表,
现在,select监听的就是两个句柄了。同理,当有多个链接请求过来时,都会把它添加到inputs列表中。
当其中的一个客户端A发送信息过来时,select会在监听的句柄列表中捕捉到客户端A这个句柄发生了变化,并把发生变化的句柄加入到rlist,但这时r不等于sk,
执行另一步操作,接收返回数据。
上面讲到了argv1参数的概述,是监听argv1这个列表,当有发生变化时才会捕捉,并加入到rlist。
argv2参数:只要在这个列表里有值,每次都会加入到wList,不同于argv1
所以可以利用argv2参数实现读写分离
server端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
import queue
ip_port = ('127.0.0.1',9999) sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建socket对象
sk.bind(ip_port) #绑定ip、端口
sk.listen(5) #监听
sk.setblocking(False) #不阻塞 inputs = [sk,]
outputs = []
message={}
while True:
rlist,wlist,eList = select.select(inputs,outputs,[],0.5)
#print("inputs:",inputs) #查看inputs列表变化
#print("rlist:",rlist) #查看rlist列表变化
#print(message)
for r in rlist:
if r == sk: #如果r是服务端
conn,address = r.accept()#
inputs.append(conn) #把连接的句柄加入inputs列表监听
message[conn] = queue.Queue() #每个新的句柄对应一个队列
print (address)
else:
client_data = r.recv(1024)
if client_data: #如果有数据,返回数据
outputs.append(r)
message[r].put(client_data) #在指定队列中插入数据
else:
inputs.remove(r) #否则移除
del message[r] #删除队列 for w in wlist: #如果wlist列表有值
try:
data =message[w].get_nowait()#去指定队列取数据
w.sendall(data)
except queue.Empty:
pass
outputs.remove(w)#因为output列表只要有数据每次都会加入wlist列表,所以发送完数据都要移除
在argv3的监听列表中,如果在跟某个socket连接通信过程中出了错误,就会把错误的句柄加到eList ,所以在加个判断,当某个socket连接通信过程中出了错误,就把这个错误的连接对象在各个列表和字典中删除。
在循环里在加上一个判断
for e in eList:
inputs.remove(e)#删除inputs监听的错误句柄
if e in outputs:#如果outputs里有也删除
outputs.remove(e)
e.close()
del message[e] #删除队列
select的4个参数都介绍完后附上server端完整代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
import queue
ip_port = ('127.0.0.1',9999) sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建socket对象
sk.bind(ip_port) #绑定ip、端口
sk.listen(5) #监听
sk.setblocking(False) #不阻塞 inputs = [sk,]
outputs = []
message={}
while True:
rlist,wlist,eList = select.select(inputs,outputs,inputs,0.5)
#print("inputs:",inputs) #查看inputs列表变化
#print("rlist:",rlist) #查看rlist列表变化
#print(message)
for r in rlist:
if r == sk: #如果r是服务端
conn,address = r.accept()#
inputs.append(conn) #把连接的句柄加入inputs列表监听
message[conn] = queue.Queue() #每个新的句柄对应一个队列
print (address)
else:
client_data = r.recv(1024)
if client_data: #如果有数据,返回数据
outputs.append(r)
message[r].put(client_data) #在指定队列中插入数据
else:
inputs.remove(r) #否则移除
del message[r] #删除队列 for w in wlist: #如果wlist列表有值
try:
data =message[w].get_nowait()#去指定队列取数据
w.sendall(data)
except queue.Empty:
pass
outputs.remove(w)#因为output列表只要有数据每次都会加入wlist列表,所以发送完数据都要移除 for e in eList:
inputs.remove(e)#删除inputs监听的错误句柄
if e in outputs:#如果outputs里有也删除
outputs.remove(e)
e.close()
del message[e] #删除队列
参考:http://www.cnblogs.com/wupeiqi/articles/5040823.html
Python—I/O多路复用的更多相关文章
- {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块
python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...
- python之IO多路复用
在python的网络编程里,socetserver是个重要的内置模块,其在内部其实就是利用了I/O多路复用.多线程和多进程技术,实现了并发通信.与多进程和多线程相比,I/O多路复用的系统开销小,系统不 ...
- 【python】-- IO多路复用(select、poll、epoll)介绍及实现
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
- python中IO多路复用、协程
一.IO多路复用 IO多路复用:检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据)(可读/可写) import socket def get_data(key): client ...
- 09 Python之IO多路复用
四种常见IO模型 阻塞IO(blocking IO).非阻塞IO(nonblocking IO).IO多路复用(IOmultiplexing).异步IO(asynchronous IO) IO发生时涉 ...
- Python poll IO多路复用
一.poll介绍 poll本质上和select没有区别,只是没有了最大连接数(linux上默认1024个)的限制,原因是它基于链表存储的. 本人的另一篇博客讲了 python select : ht ...
- Python select IO多路复用
一.select介绍 Python的select()函数是底层操作系统实现的直接接口.它监视套接字,打开文件和管道(任何带有返回有效文件描述符的fileno()方法),直到它们变得可读或可写,或者发生 ...
- python I/O多路复用 使用http完成http请求
1. 使用类实现比较方便我们使用里面的参数 2. 我们使用selector,不适用select from selectors import DefaultSelector 3. I/O多路复用是指使用 ...
- python 并发编程 多路复用IO模型
多路复用IO(IO multiplexing) 这种IO方式为事件驱动IO(event driven IO). 我们都知道,select/epoll的好处就在于单个进程process就可以同时处理多个 ...
随机推荐
- Android:理解Fragment
最近都在公司搞测试,静不下心来学android.今天就把Fragment搞懂吧. Fragment的几点要点: 1.用于大屏幕平板,容纳更多组件,可复用2.Fragment必须嵌入Activity中 ...
- 第三章 Odoo基本设置
登录 正常访问http://localhost:8069后,登录的界面如下: 这是Odoo默认的认证方式,也是我们最常见最熟悉的认证方式,7.0以前,数据库中的密码都是以明文方式存储,可以很轻松地在r ...
- .net 设置导航的当前状态
1.静态地址共用母版页时,加当前页的状态(使用加参数的方法实现): a: main.Master为链接设参数 MenuId <li> <a <%=MenuId==?" ...
- backbone学习笔记一
backbone是一个MVC单页面框架,针对传统的WEB开发B/S架构的缺点,即通过表现层的浏览器,功能层的WEB服务器,数据层的数据库服务器构架,而操作渲染过程太过复杂.
- jQuery ui autocomplete下拉列表样式失效解决,三种获取数据源方式,
jQuery有很多很多的已经实现,很漂亮的插件,autocomplete就是其中之一.jQuery ui autocomplete主要支持字符串Array.JSON两种数据格式,jQuery ui b ...
- Layer弹窗组件
layer是一款近年来备受青睐的web弹层组件,她具备全方位的解决方案,致力于服务各水平段的开发人员,您的页面会轻松地拥有丰富友好的操作体验. Layer的开发手册和下载地址 http://layer ...
- IOS彩票第三天界面
******ios6 和ios7的适配 ILBaseTableViewController.m - (void)viewDidLoad { [super viewDidLoad]; // 244 24 ...
- 【iCore3 双核心板_ uC/OS-III】例程一:认识 uC/OS-III
实验指导书及代码包下载: http://pan.baidu.com/s/1i4FuMep iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- angular+ckeditor最后上传的最后一张图片不会被添加(bug)
做法一: angularJs+ckeditor 一.页面 <textarea ckeditor required name="topicContent" ng-model=& ...
- (一)jvm
jvm,作为java平台通用性的实现基础,重要性不言而喻. 1.开发新项目,写运行脚本时要运用相关知识,确定jvm参数 2.维护老项目,需要对jvm进行性能调优 jvm内存划分: 1.程序计数器 2. ...