網路IO模型

2022-06-23 20:21:11 字數 3474 閱讀 1471

為了更好地瞭解io模型,我們需要事先回顧下:同步、非同步、阻塞、非阻塞

1.網路傳輸中的兩個階段 分別是 waitdata 和 copydata

send---copydata

recv---waitdata + copydata

記住這兩點很重要,因為這些io模型的區別就是在兩個階段上各有不同的情況。

2.阻塞io

無論是執行緒 程序 還是執行緒 程序池 統統都是阻塞io

應用程式 傳送 系統呼叫---作業系統等待資料(wait)---資料準備好 return data

所以,blocking io的特點就是在io執行的兩個階段(等待資料和拷貝資料兩個階段)都被block了。

3.非阻塞io

協程是一種非阻塞io

server.setblocking(false)將阻塞修改為非阻塞

最直接體現 recv send accept 都不會阻塞 會立即執行

但是不能保證立馬就有資料 沒有資料丟擲異常

我們需要手動捕獲異常 捕獲異常後可以處理別的任務

可以實現單執行緒併發的效果 但會大量佔用cpu資源

while true:

pass

所以,在非阻塞式io中,使用者程序其實是需要不斷的主動詢問kernel資料準備好了沒有。

4.多路複用

管理連線的一種方式

為什麼使用它? 相對於非阻塞io降低無用的系統呼叫

怎麼管?

核心函式select 幫你檢測所有的連線 找出可以被處理(可以讀寫)的連線

(預設時阻塞的 阻塞到有任意一個連線可以被處理)

結論: select的優勢在於可以處理多個連線,不適用於單個連線

一 建立連線 和管理連線

1.建立伺服器socket物件

2.將伺服器物件交給select來管理

3.一旦有客戶端發起連線 select將不在阻塞

4.select將返回一個可讀的socket物件(第一次只有伺服器)

5.伺服器的可讀代表有連線請求 需要執行accept 返回一個客戶端連線conn 由於是非阻塞 不能立即去recv

6.把客戶端socket物件也交給select來管理 將conn加入兩個被檢測的列表中

7.下一次檢測到可讀的socket 可能是伺服器 也可能客戶端 所以加上判斷 伺服器就accept 客戶端就recv

8.如果檢測到有可寫(可以send就是系統快取可用)的socket物件 則說明可以向客戶端傳送資料了

7 和 8 執行順序不是固定的

二 處理資料收發

兩個需要捕獲異常的地方

1.recv 執行第7步 表示可以讀 為什麼異常 只有一種可能客戶端斷開連線

還需要加上if not 判斷是否有資料 ;linux下 對方下線不會丟擲異常 會收到空訊息

2.send 執行第8步 表示可以寫 為什麼異常 只有一種可能客戶端斷開連線)

強調:1. 如果處理的連線數不是很高的話,使用select/epoll的web server不一定比

使用multi-threading + blocking io的web server效能更好,可能延遲還更大。

select/epoll的優勢並不是對於單個連線能處理得更快,而是在於能處理更多的連線。

2. 在多路複用模型中,對於每一個socket,一般都設定成為non-blocking,但是,如上圖所示,

整個使用者的process其實是一直被block的。只不過process是被select這個函式block,而不是被socket io給block。

結論: select的優勢在於可以處理多個連線,不適用於單個連線

5.非同步io 網路io+本地io 都適用

io包括 網路io 本地io

上面的三種io模型描述的都是網路io,不是本地io的問題

解決的方案就是:

將同步的io操作改成非同步的io操作 在io期間 可以執行其他的任務

最終的解決方案就是協程 使用asyncio模組 該模快實現非同步io 內部使用協程實現

它的流程:

使用者程序發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,

當它受到一個asynchronous read之後,首先它會立刻返回,所以不會對使用者程序產生任何block。

然後,kernel會等待資料準備完成,然後將資料拷貝到使用者記憶體,

當這一切都完成之後,kernel會給使用者程序傳送一個signal,告訴它read操作完成了。

socketserver

是什麼? 對伺服器端的socket的封裝

封裝了多執行緒 多程序 io模型,支撐高併發 高併發 的socket套接字

為什麼用? 簡化**

使用方法:

socketserver (forkingudp forkingtcp windows無法使用)

核心類 threadingudpserver threadingtcpserver

threadingtcpserver 例項化時 傳入伺服器地址 和 自定義的一個資料處理類

自定義類需要繼承baserequesthandler類中需包含handle函式

物件呼叫serve_forever

tcp服務端

import socketserver

class myhandler(socketserver.baserequesthandler):

def handler(self):

while true:

try:

data=self.request.recv(1024)

if not data:break

print(data.decode('utf-8'))

self.request.send(data.upper())

except connectionreseterror:

break

self.request.close()

if __name__ == '__main__':

server=socketserver.threadingtcpserver(('127.0.0.1',8080),myhandler)

server.serve_forever()

udp服務端

import socketserver

class myhandler(socketserver.baserequesthandler):

def handle(self):

data,server=self.request

print(data.decode('utf-8'))

server.sendto(data.upper(),self.client_address)

if __name__ == '__main__':

server=socketserver.threadingudpserver(('127.0.0.1',8080),myhandler)

server.serve_forever()

Python IO模型

比如,你新買了一臺電腦,我們開機發現,連執行都執行不了,我們買的只是一堆硬體,要想讓電腦執行起來, 靠的就是作業系統,作業系統就是操作軟體的軟體,不僅能操作軟體,還能操控硬體。 核心態,就是留給作業系統專用,而使用者的程序是不可以在,核心裡執行的。 而使用者態就是,我們的程序了,比如360,qq,pyc...

IO模型 IO多路複用

用socket 一定會用到accept recv recvfrom這些方法 正常情況下 accept recv recvfrom都是阻塞的...

Python之阻塞IO模型與非阻塞IO模型

python之阻塞io模型與非阻塞io模型 io模型 1 阻塞io 全程阻塞 2 非阻塞io 傳送多次系統呼叫 優點 wait for data時無阻塞 缺點 1 系統呼叫太多 2 資料不是實時接受的 兩個階段 wait for data 非阻塞 copy data 阻塞 3 io多路複用 監聽多個...