1. 程式人生 > >python例項解釋五種IO模型(3)--------IO多路複用

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個描述符。遍歷返回的可讀列表就可以分別對就緒的描述符進行相應的操作。