python实例解释五种IO模型(3)--------IO多路复用
0.IO多路复用
IO多路复用的模型如上图所示,有了IO多路复用,我们就可以调用select或者poll,用户程序阻塞在这两个系统调用的某一个之上,而不是阻塞在真正的IO系统调用之上。IO多路复用的优点在于,他可以同时等待多个描述符就绪。下面看一个例子
1. select实例
服务端程序如下:
import select
import socket
import time
s = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 12345 # 设置端口
s.bind((host, port)) # 绑定端口
s.listen(5) # 监听,等待客户端连接
s.setblocking(False) #设置监听socket为非阻塞
inputs = [s]
outputs = []
while inputs:
print ('waiting for the next event')
readable, writable, exceptional = select.select(inputs, outputs, inputs)
for v in readable:
if v is s:
connection, client_addr = v.accept()
print ('connection from', client_addr)
connection.setblocking(0) #设置连接socket为非阻塞
inputs.append(connection) #添加socket至input列表
else :
data = v.recv(1024)
data = str(data,'utf-8')
print(data)
if data == '88':
inputs.remove(v)
v.close()
select函数有四个参数,第一个是需要监听的读描述符列表,第二个是写描述符列表,第三个是异常描述符列表,第四个是超时时间。第四个参数是可选的,如果没有设置,则永不超时。select返回三个列表,分别是读就绪的描述符、写就绪的描述符和异常描述符。
客户端程序
import socket # 导入 socket 模块
s = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 12345 # 设置端口号
s.connect((host, port))
print("connected to server")
while(True):
data = input()
s.send(bytes(data,'utf-8'))
if data == '88':
s.close()
break
首先启动服务端程序,程序打印一行信息后,阻塞在select调用。
启动一个客户端程序后,此时监听描述符变为可读,进入for循环,调用accept()函数,将返回的连接描述符设置为非阻塞,写入inputs列表。同时打印出客户端的地址和端口号
再启动一个客户端程序,重复上面的过程
这样selec函数就监听了3个描述符。遍历返回的可读列表就可以分别对就绪的描述符进行相应的操作。