Python select模块 I/O多路复用
来源:互联网 发布:mysql 建表时创建索引 编辑:程序博客网 时间:2024/06/07 06:26
Python select模块 I/O多路复用
Python 在 select 模块中提供了异步 I/O(Asynchronous I/O),与 Linux 下的 select 机制相似,但进行一些简化
select 模块
select()的机制中提供一fd_set的数据结构
,实际上是一long类型的数组,
每一个数组元素都能与一打开的文件句柄(不管是Socket句柄,还是其他文件或命名管道或设备句柄)建立联系
,建立联系的工作由程序员完成,
当调用select()
时,由内核根据IO状态修改
fd_set的内容,
由此来通知执行了select()的进程哪一Socket或文件可读或可写。主要用于Socket通信当中。
select怎么调用
并且关注了几个描述字–>系统通知我哪个描述符(某个socket)可读或者可写的时候,它可以给你一个通知,去调用select()
select调用后发生什么
调用了一个 select 函数,select 函数就返回了,告诉我们套接口已经可读,
然后我们去调用read()读这个套接口,可以保证每次read都能读到有效数据而不做纯返回-1和EAGAIN的无用功
可以用阻塞的read或者非阻塞的 read,阻塞 read 是无数据可读就阻塞进程,非阻塞 read是无数据可读就返回一个 EWOULDBLOCK 错误。
非阻塞式I/O编程特点
- 如果一个发现I/O有输入,读取的过程中,另外一个也有了输入,这时候不会产生任何反应.这就需要你的程序语句去用到select函数的时候才知道有数据输入。
- 程序去select的时候,如果没有数据输入,程序会一直等待,直到有数据为止,也就是程序中无需循环和sleep。
阻塞方式block
顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回 诸如connect、accept、recv或recvfrom这样的阻塞程序
非阻塞方式non-block
就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生,则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高
总结:select主要用于socket通信当中,能监视我们需要的文件描述变化。
I/O多路复用技术
某个socket可读或者可写的时候,它可以给你一个通知。这样当配合非阻塞的socket使用时,只有当系统通知我哪个描述符可读了,我才去执行read操作,可以保证每次read都能读到有效数据而不做纯返回-1和EAGAIN的无用功
操作系统的这个功能通过select/poll/epoll/kqueue之类的系统调用函数来使用,这些函数都可以同时监视多个描述符的读写就绪状况,这样,多个描述符的I/O操作都能在一个线程内并发交替地顺序完成,这就叫I/O多路复用,这里的“复用”指的是复用同一个线程。
举个例子子
作者:郭春阳
链接:https://www.zhihu.com/question/28594409/answer/52835876
来源:知乎
模拟一个tcp服务器处理30个客户socket。假设你是一个老师,让30个学生解答一道题目,然后检查学生做的是否正确,你有下面几个选择:
1. 第一种选择:按顺序逐个检查,先检查A,然后是B,之后是C、D。。。这中间如果有一个学生卡主,全班都会被耽误。这种模式就好比,你用循环挨个处理socket,根本不具有并发能力。
2. 第二种选择:你创建30个分身,每个分身检查一个学生的答案是否正确。 这种类似于为每一个用户创建一个进程或者线程处理连接。
3. 第三种选择,你站在讲台上等,谁解答完谁举手。这时C、D举手,表示他们解答问题完毕,你下去依次检查C、D的答案,然后继续回到讲台上等。此时E、A又举手,然后去处理E和A。。。
这种就是IO复用模型,Linux下的select、poll和epoll就是干这个的。
将用户socket对应的fd注册进epoll,然后epoll帮你监听哪些socket上有消息到达,这样就避免了大量的无用操作。此时的socket应该采用非阻塞模式。这样,整个过程只在调用select、poll、epoll这些调用的时候才会阻塞,收发客户消息是不会阻塞的,整个进程或者线程就被充分利用起来,这就是事件驱动,所谓的reactor模式。
多线程来并行处理多路 socket I/O
select 方法允许你响应不同 socket 的多个事件以及其它不同事件。
例如:
你可以让 select在某个 socket 有数据到达时,或者当某个 socket 可以写数据时,又或者是当某个 socket 发生错误时通知你,
好处是你可以同时响应很多 socket 的多个事件
。
Linux 下 C 语言的 select 使用到 位图
来表示我们要关注哪些文件描述符
的事件 python
中使用 list
来表示我们监控的文件描述符
当有事件到达时,返回
的也是文件描述符的 list,表示这些文件有事件到达
表示等待从标准输入中获得输入
rlist,wlist,elist = select.select([sys.stdin],[],[])print sys.stdin.read()
参数:
可接受四个参数(前三个必须)
select 方法的前三个参数都是 list 类型,
分别代表读事件
、写事件
、错误事件
,timeout 超过时间
返回值:
同样方法返回值
也是三个 list
包含的是哪些事件(读、写、异常)满足了。
上面的例子,参数只有一个事件 sys.stdin–>表示只关心标准输入事件
select 返回时 rlist 只会是 [sys.stdin]–>表示可以从 stdin 中读入数据了
我们使用 read 方法
来读入数据。
select 对于 socket 描述符也是有效的
创建了两个 socket 客户端连接到远程服务器,
select
–>用来监控哪个 socket 有数据到达:
import socketimport selectsocket1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)socket2 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)socket1.connect(('192.168.1.1',25))socket2.connect(('192.168.1.1',25))while 1: #等待读一个事件,参数是,返回的是读到的事件 rlist,wlist,elist = select.select([socket1,scoket2],[],[],5) # if [rlist,wlist,elist ] == [[],[],[]]: print "five seconds elapsed\n" else: for sock in rlist: print sock.recv(100)
- Python select模块 I/O多路复用
- I/O多路复用select
- 多路复用I/O--select
- Python I/O多路复用
- I/O多路复用 select模型
- I/O多路复用之select
- I/O 多路复用之select
- I/O多路复用之select
- select实现I/O多路复用
- I/O多路复用(select)
- select函数:I/O多路复用
- I/O多路复用- select函数
- I/O多路复用之select
- I/O多路复用之select
- I/O多路复用之select
- I/O多路复用之select
- I/O多路复用之select
- I/O多路复用select服务器
- C++ Primer之再续前缘
- docker containerd shim分析
- 技术分析之Hibernate的关联关系映射之一对多映射
- Anaconda3+opencv
- jsonp之callback
- Python select模块 I/O多路复用
- 磁罗盘分析
- 我对linux理解之driver_register
- GetProcessTokenElevationTypeStaus
- 动画初学习
- HTML5-H5的变化
- 开发常用CSS
- JavaEE的13种核心技术
- 基于tcp、数据库的员工管理系统