IO程式設計 二 NIO程式設計概念

2021-10-01 17:16:57 字數 1701 閱讀 5527

注意標題.此章只是讓我們對nio有個概念,而不是讓你真正的去敲或者熟悉以下**

傳統bio程式設計如圖1,來乙個客戶端連線就需要乙個新的執行緒.

而nio中會把新的連線註冊到 selector 上,然後,通過檢查這個 selector,就可以批量監測出有資料可讀的連線,進而讀取資料

舉個例子:

幼兒園小朋友要上廁所,但是太小不會表達.

bio乙個小朋友(客戶端連線)配乙個老師(執行緒),同時老師還要不停的輪詢(迴圈)小朋友是否需要上廁所.然後再乙個個帶小朋友去廁所

nio50個小朋友配乙個老師,老師統一詢問是否有小朋友需要上廁所(客戶端是否有資料傳輸),如果有則批量帶去上廁所(接收資料)

由於 nio 模型中線程數量大大降低,執行緒切換效率因此也大幅度提高

io 讀寫是面向流的,一次性只能從流中讀取乙個或者多個位元組,並且讀完之後流無法再讀取,你需要自己快取資料。 而 nio 的讀寫是面向 buffer 的,你可以隨意讀取裡面任何乙個位元組資料,不需要你自己快取資料,這一切只需要移動讀寫指標即可。

下面是jdk 原生的 nio 來實現服務端**(從網上copy的 來自閃電俠)

public class nioserver  finally }}

}}} catch (ioexception ignored)

}).start();

new thread(() -> finally }}

}}} catch (ioexception ignored)

}).start();}}

核心思路

nio 模型中通常會有兩個執行緒,每個執行緒繫結乙個輪詢器 selector ,在我們這個例子中serverselector負責輪詢是否有新的連線,clientselector負責輪詢連線是否有資料可讀

服務端監測到新的連線之後,不再建立乙個新的執行緒,而是直接將新連線繫結到clientselector上,這樣就不用 io 模型中 1w 個 while 迴圈在死等,參見(1)

clientselector被乙個 while 死迴圈包裹著,如果在某一時刻有多條連線有資料可讀,那麼通過clientselector.select(1)方法可以輪詢出來,進而批量處理,參見(2)

資料的讀寫面向 buffer,參見(3)

不用對**的細節深究到底。總之,強烈不建議直接基於jdk原生nio來進行網路開發

jdk 的 nio 程式設計需要了解很多的概念,程式設計複雜,對 nio 入門非常不友好,程式設計模型不友好,bytebuffer 的 api 簡直***

對 nio 程式設計來說,乙個比較合適的執行緒模型能充分發揮它的優勢,而 jdk 沒有給你實現,你需要自己實現,就連簡單的自定義協議拆包都要你自己實現

jdk 的 nio 底層由 epoll 實現,該實現飽受詬病的空輪詢 bug 會導致 cpu 飆公升 100%

專案龐大之後,自行實現的 nio 很容易出現各類 bug,維護成本較高,上面這一坨**我都不能保證沒有 bug

所以netty 橫空出世!

IO與NIO網路程式設計模型

一 bio bolcking io 阻塞分析 阻塞點 1.建立服務埠 serversocket serversocket new serversocket 12345 獲取socket套接字 socket socket serversocket.accept 阻塞等待客戶端連線 2.獲取客戶端輸入流...

NIO程式設計

1.客戶端關閉 的時候會拋異常 死迴圈 int read channel.read buffer if read 0 else 客戶端關閉 key.cancel 登出當前key 2.selector.select 阻塞 為什麼說nio 是非阻塞的io selector.select selector...

NIO程式設計要點總結二

承接上篇 nio程式設計要點總結一,繼續進行nio要點梳理 3.selector方法說明 1 selector.open 建立並返回乙個選擇器物件 2 selector.select 監控所有通道channel,有事件發生則會將其對應的selectionkey加入到內部集合並將該集合的元素個數返回 ...