網路IO模型

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

為了更好地了解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()

網路IO模型

io有兩種操作,同步io和非同步io。同步io指的是,必須等待io操作完成後,控制權才返回給使用者程序。非同步io指的是,無須等待io操作完成,就將控制權返回給使用者程序。網路中的io,由於不同的io裝置有著不同的特點,網路通訊中往往需要等待。常見的有以下4種情況。1 輸入操作 等待資料到達套接字接...

網路IO模型

一 阻塞io模型 阻塞io基於socket程式 原理 recv接收資料時,不是直接接收資料,而是程式將系統呼叫的命令傳送到作業系統 當作業系統收到接收資料的請求,若此時無資料,作業系統會繼續等待,處於等待資料階段 wait for data階段 這個階段相對漫長 當資料來了,作業系統會拷貝資料 co...

網路I O模型 5種常見的網路I O模型

阻塞與非阻塞 阻塞就是卡在那兒什麼也不做,雙方之間也沒有資訊溝通。非阻塞就是即使對方不能馬上完成請求,雙方之間也有資訊的溝通。同步與非同步 同步就是一件事件只由乙個過程處理完成,不論阻塞與非阻塞,最後完成這個事情的都是同乙個過程 非同步就是一件事由兩個過程完成,前面乙個過程通知,後面乙個過程接受返回...