Netty-01-NIO基礎

来源:https://www.cnblogs.com/lcha-coding/archive/2022/06/28/16421747.html
-Advertisement-
Play Games

一. NIO 基礎 non-blocking io 非阻塞 IO 1. 三大組件 1.1 Channel & Buffer channel 有一點類似於 stream,它就是讀寫數據的雙向通道,可以從 channel 將數據讀入 buffer,也可以將 buffer 的數據寫入 channel,而之 ...


一. NIO 基礎

non-blocking io 非阻塞 IO

1. 三大組件

1.1 Channel & Buffer

channel 有一點類似於 stream,它就是讀寫數據的雙向通道,可以從 channel 將數據讀入 buffer,也可以將 buffer 的數據寫入 channel,而之前的 stream 要麼是輸入,要麼是輸出,channel 比 stream 更為底層

graph LR channel --> buffer buffer --> channel

常見的 Channel 有

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

buffer 則用來緩衝讀寫數據,常見的 buffer 有

  • ByteBuffer
    • MappedByteBuffer
    • DirectByteBuffer
    • HeapByteBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer
  • CharBuffer

1.2 Selector

selector 單從字面意思不好理解,需要結合伺服器的設計演化來理解它的用途

多線程版設計

graph TD subgraph 多線程版 t1(thread) --> s1(socket1) t2(thread) --> s2(socket2) t3(thread) --> s3(socket3) end

⚠️ 多線程版缺點

  • 記憶體占用高
  • 線程上下文切換成本高
  • 只適合連接數少的場景

線程池版設計

graph TD subgraph 線程池版 t4(thread) --> s4(socket1) t5(thread) --> s5(socket2) t4(thread) -.-> s6(socket3) t5(thread) -.-> s7(socket4) end

⚠️ 線程池版缺點

  • 阻塞模式下,線程僅能處理一個 socket 連接
  • 僅適合短連接場景

selector 版設計

selector 的作用就是配合一個線程來管理多個 channel,獲取這些 channel 上發生的事件,這些 channel 工作在非阻塞模式下,不會讓線程吊死在一個 channel 上。適合連接數特別多,但流量低的場景(low traffic)

graph TD subgraph selector 版 thread --> selector selector --> c1(channel) selector --> c2(channel) selector --> c3(channel) end

調用 selector 的 select() 會阻塞直到 channel 發生了讀寫就緒事件,這些事件發生,select 方法就會返回這些事件交給 thread 來處理

2. ByteBuffer

有一普通文本文件 data.txt,內容為

1234567890abcd

使用 FileChannel 來讀取文件內容

@Slf4j
public class ChannelDemo1 {
    public static void main(String[] args) {
        try (RandomAccessFile file = new RandomAccessFile("helloword/data.txt", "rw")) {
            FileChannel channel = file.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(10);
            do {
                // 向 buffer 寫入
                int len = channel.read(buffer);
                log.debug("讀到位元組數:{}", len);
                if (len == -1) {
                    break;
                }
                // 切換 buffer 讀模式
                buffer.flip();
                while(buffer.hasRemaining()) {
                    log.debug("{}", (char)buffer.get());
                }
                // 切換 buffer 寫模式
                buffer.clear();
            } while (true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

輸出

10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 讀到位元組數:10
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 1
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 2
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 3
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 4
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 5
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 6
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 7
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 8
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 9
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 0
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 讀到位元組數:4
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - a
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - b
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - c
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - d
10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 讀到位元組數:-1

2.1 ByteBuffer 正確使用姿勢

  1. 向 buffer 寫入數據,例如調用 channel.read(buffer)
  2. 調用 flip() 切換至讀模式
  3. 從 buffer 讀取數據,例如調用 buffer.get()
  4. 調用 clear() 或 compact() 切換至寫模式
  5. 重覆 1~4 步驟

2.2 ByteBuffer 結構

ByteBuffer 有以下重要屬性

  • capacity
  • position
  • limit

一開始

寫模式下,position 是寫入位置,limit 等於容量,下圖表示寫入了 4 個位元組後的狀態

flip 動作發生後,position 切換為讀取位置,limit 切換為讀取限制

讀取 4 個位元組後,狀態

clear 動作發生後,狀態

compact 方法,是把未讀完的部分向前壓縮,然後切換至寫模式


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一種JavaScript響應式系統實現 根據VueJs核心團隊成員霍春陽《Vue.js設計與實現》第四章前三節整理而成 1. 響應式數據與副作用函數 1.1 副作用函數 會產生副作用的函數。 如下示例所示: function effect () { document.body.innerText = ...
  • pageClass: home-page-class 鯉魚跳龍門動畫 1. 需求 年中618營銷活動要求做一個鯉魚跳龍門的動畫,產品參考了支付寶上的一個動畫,要求模仿這個來做一個類似的動畫。產品提供的截屏視頻如下: 圖1 從這個視頻里得到的信息,我們可以把動畫分解一下: 321倒計時結束,動畫開始播 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 寫在前面 雖然說Fetch API已經使用率已經非常的高了,但是在一些老的瀏覽器還是不支持的,而且axios仍然每周都保持2000多萬的下載量,這就說明瞭axios仍然存在不可撼動的地位,接下來我們就一步一步的去封裝,實現一個靈活、可復用 ...
  • 前言 前段時間,部門的前端項目遷移到 monorepo 架構,筆者在其中負責跟 git 工作流相關的事情,其中就包括 git hooks 相關的工程化的實踐。用到了一些常用的相關工具如 husky、lint-staged、commitizen、commit-lint 等,以此文記錄一下整個的實踐過程 ...
  • 1、網頁基本信息 | <!DOCTYPE html> | 瀏覽器使用的規範 | | | | | <head> | 網頁頭 | | <body> | 主體部分 | | <meta> | 元數據 | meta的name屬性(瞭解) | Keyword(關鍵字) | 為搜索引擎提供的關鍵字列表 | | | ...
  • 最新的一份《The State of WebAssembly 2022》調查報告已出爐,“對於 WebAssembly 來說,這是相當不錯的一年”。報告的一些重點內容包括:Rust 的使用率和渴望度持續攀升Python 的使用量有了很大的提升JavaScript 已經成為一種可行的 WebAssem ...
  • 迴圈迭代: 1 public class steps { 2 public int js(int n) { 3 int one = 2; //初始化為第三級臺階最後跨一步的走法 4 int two = 1; //初始化為第三級臺階最後跨兩步(一下邁過去兩個臺階)的走法 5 int sum = 0; ...
  • 基本概念 指針代表記憶體地址。 通常在類型關鍵字的後面加字元*來表示指針,表示指針指向什麼類型的值。比如,char*表示一個指向字元的指針,float*表示一個指向float類型值的指針。 指針指向的可能還是指針,這時要用兩個星號**表示。 int** foo; 指針變數初始化 聲明指針變數之後,編譯 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...