python IO模型

來源:互聯網
上載者:User

標籤:server   系統   添加   報錯   output   NPU   監聽   非同步io   直接   

詳細帶圖

第一種IO模型
阻塞

 

第二種IO模型
非阻塞IO
原理:由阻塞改為非阻塞,每隔一段時間回來看看(每每看一次,核心態會發送一次系統調用),若沒有幹其他事情(適用於代碼量小),進程主動輪詢
當伺服器端通訊端被setblocking(false),通訊端為非阻塞通訊端,當接收不到用戶端連結時,直接觸發異常(證明現階段CPU空閑,可以做其他事情)。所以可以在異常處理處理其他任務。

 

缺點
發送太多次系統調用
資料得不到及時處理

 

第三種IO模型
IO多工(單線程下實現並發,原理就是利用IO空閑時間實現並發)(select ,poll,epoll)
select
select函數是系統調用介面。並且select也是會阻塞,
但其好處是同時可監控多個連結,這是決定了為何如此流行.
講到這裡還是莫名其妙,但是可以把socket.accpet()返回的conn添加至監聽列表裡,就明白了。因為監聽那麼多,總有一個是核心態有資料的,也就是說總會可以操作的
注意的是:預設,若核心態的資料沒有取至使用者態,則返回的可讀列表裡會一直存在該通訊端。還有監聽數不能超過1024

# select 類比一個socket server,注意socket必須在非阻塞情況下才能實現IO多工。# 接下來通過例子瞭解select 是如何通過單進程實現同時處理多個非阻塞的socket串連的。#server端import selectimport socketimport queueserver = socket.socket()server.bind((‘localhost‘,9000))server.listen(1000)server.setblocking(False)  # 設定成非阻塞模式,accept和recv都非阻塞# 這裡如果直接 server.accept() ,如果沒有串連會報錯,所以有資料才調他們# BlockIOError:[WinError 10035] 無法立即完成一個非阻塞性通訊端操作。msg_dic = {}inputs = [server,]  # 交給核心、select檢測的列表。# 必須有一個值,讓select檢測,否則報錯提供無效參數。# 沒有其他串連之前,自己就是個socket,自己就是個串連,檢測自己。活動了說明有連結outputs = []  # 你往裡面放什麼,下一次就出來了while True:    readable, writeable, exceptional = select.select(inputs, outputs, inputs)  # 定義檢測    #新來串連                                        檢測列表         異常(斷開)    # 異常的也是inputs是: 檢測那些串連的存在異常    print(readable,writeable,exceptional)    for r in readable:        if r is server:  # 有資料,代表來了一個新串連            conn, addr = server.accept()            print("來了個新串連",addr)            inputs.append(conn)  # 把串連加到檢測列表裡,如果這個串連活動了,就說明資料來了            # inputs = [server.conn] # 【conn】只返回活動的串連,但怎麼確定是誰活動了            # 如果server活動,則來了新串連,conn活動則來資料            msg_dic[conn] = queue.Queue()  # 初始化一個隊列,後面存要返回給這個用戶端的資料        else:            try :                data = r.recv(1024)  # 注意這裡是r,而不是conn,多個串連的情況                print("收到資料",data)                # r.send(data) # 不能直接發,如果用戶端不收,資料就沒了                msg_dic[r].put(data)  # 往裡面放資料                outputs.append(r)  # 放入返回的串連隊列裡            except ConnectionResetError as e:                print("用戶端斷開了",r)                if r in outputs:                    outputs.remove(r) #清理已斷開的串連                inputs.remove(r) #清理已斷開的串連                del msg_dic[r] ##清理已斷開的串連    for w in writeable:  # 要返回給用戶端的串連列表        data_to_client = msg_dic[w].get()  # 在字典裡取資料        w.send(data_to_client)  # 返回給用戶端        outputs.remove(w)  # 刪除這個資料,確保下次迴圈的時候不返回這個已經處理完的串連了。    for e in exceptional:  # 如果串連斷開,刪除串連相關資料        if e in outputs:            outputs.remove(e)        inputs.remove(e)        del msg_dic[e]#*************************clientimport socketclient = socket.socket()client.connect((‘localhost‘, 9000))while True:    cmd = input(‘>>> ‘).strip()    if len(cmd) == 0 : continue    client.send(cmd.encode(‘utf-8‘))    data = client.recv(1024)    print(data.decode())client.close()

 

poll
相比select,就是一點,就是把最大連結數提高了

 

epoll
epoll實現原理跟select一樣(原理圖一樣),但是實現機制不同(也就是,資料來了,是怎麼找到是指定通訊端的)

 

select內部原理是採取輪詢,就好比,在一間教室裡老師聽到有一學生拍了下桌子,但不知道具體誰拍的,
只有一個一個問。所以很多時間都消耗在輪詢問上面了(是每一次有資料到來時候,都要輪詢)
epoll內部原理是自報家門,就好比,學生不拍桌子,直接站起來我是誰,我要反了
Ngexi伺服器底層就是epoll,多進程多線程開得不多,但是一個線程裡面通過epoll實現多串連

 

非同步IO

非同步是整個過程中一點阻塞都沒有。你發完請求你就去做其他事情,等到核心把資料收到且複製到使用者態,再發給你一個訊號。
所以說以上IO多工,不是非同步。

同步IO
在IO操作完成之前存在阻塞。而非同步IO是毫無阻塞。所以多工都屬於同步IO

 

python IO模型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.