python例項解釋五種IO模型(3)--------IO多路複用
阿新 • • 發佈:2019-01-06
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個描述符。遍歷返回的可讀列表就可以分別對就緒的描述符進行相應的操作。