Netty之十大核心模块组件介绍
1.Bootstrap、ServerBootstrap
(1)簡介
Bootstrap 意思是引導,一個 Netty 應用通常由一個 Bootstrap 開始,主要作用是配置整個 Netty 程序,串聯各個組件,Netty 中 Bootstrap 類是客戶端程序的啟動引導類,ServerBootstrap 是服務端啟動引導類
(2)常用方法
| group(EventLoopGroup parentGroup, EventLoopGroup childGroup) | 該方法用于服務器端,用來設置兩個 EventLoop |
| group(EventLoopGroup group) | 該方法用于客戶端,用來設置一個 EventLoop |
| channel(Class<? extends C> channelClass) | 該方法用來設置一個服務器端的通道實現 |
| option(ChannelOption<T> option, T value) | 用來給 ServerChannel 添加配置 |
| childOption(ChannelOption<T> childOption, T value) | 用來給接收到的通道添加配置 |
| childHandler(ChannelHandler childHandler) | 該方法用來設置業務處理類 |
| bind(int inetPort) | 該方法用于服務器端,用來設置占用的端口號 |
| connect(String inetHost, int inetPort) | 該方法用于客戶端,用來連接服務器端 |
2.Future、ChannelFuture
(1)簡介
Netty 中所有的 IO 操作都是異步的,不能立刻得知消息是否被正確處理。但是可以過一會等它執行完成或者直接注冊一個監聽,具體的實現就是通過 Future 和 ChannelFutures,他們可以注冊一個監聽,當操作執行成功或失敗時監聽會自動觸發注冊的監聽事件
(2)常用方法
| Channel channel() | 返回當前正在進行 IO 操作的通道 |
| ChannelFuture sync() | 等待異步操作執行完畢 |
3.Channel
-
Netty 網絡通信的組件,能夠用于執行網絡 I/O 操作
-
通過Channel可獲得當前網絡連接的通道的狀態
-
通過Channel可獲得網絡連接的配置參數(例如接收緩沖區大小)
-
Channel 提供異步的網絡 I/O 操作(如建立連接,讀寫,綁定端口),異步調用意味著任何 I/O 調用都將立即返回,并且不保證在調用結束時所請求的 I/O 操作已完成
-
調用立即返回一個 ChannelFuture 實例,通過注冊監聽器到ChannelFuture 上,可以 I/O 操作成功、失敗或取消時回調通知調用方
-
支持關聯 I/O 操作與對應的處理程序
-
不同協議、不同的阻塞類型的連接都有不同的 Channel 類型與之對應,常用的 Channel 類型:
| NioSocketChannel | 異步的客戶端 TCP Socket 連接 |
| NioServerSocketChannel | 異步的服務器端 TCP Socket 連接 |
| NioDatagramChannel | 異步的 UDP 連接 |
| NioSctpChannel | 異步的客戶端 Sctp 連接 |
| NioSctpServerChannel | 異步的 Sctp 服務器端連接,這些通道涵蓋了 UDP 和 TCP 網絡 IO 以及文件 IO |
4.Selector
-
Netty 基于 Selector 對象實現 I/O 多路復用,通過 Selector 一個線程可以監聽多個連接的 Channel 事件
-
當向一個 Selector 中注冊 Channel 后,Selector 內部的機制就可以自動不斷地查詢(Select) 這些注冊的 Channel 是否有已就緒的 I/O 事件(例如可讀,可寫,網絡連接完成等),這樣程序就可以很簡單地使用一個線程高效地管理多個 Channel
5.ChannelHandler及其實現類
-
ChannelHandler 是一個接口,處理 I/O 事件或攔截 I/O 操作,并將其轉發到其 ChannelPipeline(業務處理鏈) 中的下一個處理程序
-
ChannelHandler 本身并沒有提供很多方法,因為這個接口有許多的方法需要實現,方便使用期間,可以繼承它的子類
-
ChannelHandler 及其實現類的類圖如下:
?
-
我們經常需要自定義一個 Handler 類去繼承ChannelInboundHandlerAdapter,然后通過重寫相應方法實現業務邏輯
6.Pipeline和ChannelPipeline
-
ChannelPipeline 是一個 Handler 的集合,它負責處理和攔截 inbound 或者 outbound 的事件和操作,相當于 一個貫穿 Netty 的鏈。(也可以這樣理解:ChannelPipeline 是 保存 ChannelHandler 的 List,用于處理或攔截 Channel 的入站事件和出站操作)
-
ChannelPipeline 實現了一種高級形式的攔截過濾器模式,使用戶可以完全控制事件的處理方式,以及 Channel 中各個的 ChannelHandler 如何相互交互
-
在 Netty 中每個 Channel 都有且僅有一個 ChannelPipeline 與之對應,它們的組成關系如下:
-
一個Channel包含了一個ChannelPipeline,而ChannelPipeline中又維護了一個由ChannelHandlerContext組成的雙向鏈表,并且每個ChannelHandlerContext中又關聯著一個ChannelHandler
-
入站時間和出站時間在一個雙向鏈表中,入站事件會從鏈表head往后傳遞到最后一個入站的handler,出站事件會從鏈表tail往前傳遞到最前一個出站的handler,兩種類型的handler互不干擾
-
?
-
常用方法
| addFirst(ChannelHandler… handlers) | 把一個業務處理類(handler)添加到鏈中的第一個位置 |
| addLast(ChannelHandler… handlers) | 把一個業務處理類(handler)添加到鏈中的最后一個位置 |
7.ChannelHandlerContext
-
保存 Channel 相關的所有上下文信息,同時關聯一個 ChannelHandler 對象
-
ChannelHandlerContext中包含一個具體的事件處理器 ChannelHandler,同時 ChannelHandlerContext 中也綁定了對應的 pipeline 和 Channel 的信息,方便對 ChannelHandler 進行調用
-
常用方法
| close() | 關閉通道 |
| flush() | 刷新 |
| writeAndFlush(object msg) | 將數據寫到ChannelPipeline中當前ChannelHandler的下一個ChannelHandler開始處理 |
8.ChannelOption
-
Netty 在創建 Channel 實例后,一般都需要設置 ChannelOption 參數
-
ChannelOption 參數如下:
-
ChannelOption.SO_BACKLOG:對應TCP/IP協議listen函數中的backlog參數,用來初始化服務器可連接隊列。服務端處理客戶端連接請求是順序處理的,所以同一時間只能處理一個客戶端連接。多個客戶端來的時候,服務端將不能處理的客戶端連接請求放在隊列中等待處理,backlog參數指定了隊列的大小
-
ChannelOption.SO_KEEPALIVE:一直保持連接活動狀態
-
9.EventLoopGroup
-
EventLoopGroup 是一組 EventLoop 的抽象,Netty 為了更好的利用多核 CPU 資源,一般會有多個 EventLoop 同時工作,每個 EventLoop 維護著一個 Selector 實例
-
EventLoopGroup 提供 next 接口,可以從組里面按照一定規則獲取其中一個 EventLoop 來處理任務。在 Netty 服務器端編程中,我們一般都需要提供兩個 EventLoopGroup,例如:BossEventLoopGroup 和 WorkerEventLoopGroup
-
通常一個服務端口即一個ServerSocketChannel對應一個Selector和一個EventLoop線程。BossEventLoop 負責接收客戶端的連接并將 SocketChannel 交給 WorkerEventLoopGroup 來進行 IO 處理,如下圖所示
?
10.Unpooled 類
-
Netty 提供一個專門用來操作緩沖區(即 Netty 的數據容器)的工具類
-
常用方法如下
-
ButeBuf的基本使用演示
案例1:
public class NettyByteBuf01 {public static void main(String[] args) { ? ?//創建一個ByteBuf//說明//1. 創建 對象,該對象包含一個數組arr , 是一個byte[10]//2. 在netty 的buffer中,不需要使用flip 進行反轉// ? 底層維護了 readerindex 和 writerIndex//3. 通過 readerindex 和 writerIndex 和 capacity, 將buffer分成三個區域// 0---readerindex 已經讀取的區域// readerindex---writerIndex , 可讀的區域// writerIndex -- capacity, 可寫的區域ByteBuf buffer = Unpooled.buffer(10); ?for(int i = 0; i < 10; i++) {buffer.writeByte(i);} ?System.out.println("capacity=" + buffer.capacity());//10//輸出 // ? ? ? for(int i = 0; i<buffer.capacity(); i++) { // ? ? ? ? ? System.out.println(buffer.getByte(i)); // ? ? ? }for(int i = 0; i < buffer.capacity(); i++) {System.out.println(buffer.readByte());}System.out.println("執行完畢");} }案例2:
public class NettyByteBuf02 {public static void main(String[] args) { ?//創建ByteBufByteBuf byteBuf = Unpooled.copiedBuffer("hello,world!", Charset.forName("utf-8")); ?//使用相關的方法if(byteBuf.hasArray()) { // true ?byte[] content = byteBuf.array(); ?//將 content 轉成字符串System.out.println(new String(content, Charset.forName("utf-8"))); ?System.out.println("byteBuf=" + byteBuf); ?System.out.println(byteBuf.arrayOffset()); // 0System.out.println(byteBuf.readerIndex()); // 0System.out.println(byteBuf.writerIndex()); // 12System.out.println(byteBuf.capacity()); // 36 ?//System.out.println(byteBuf.readByte()); //System.out.println(byteBuf.getByte(0)); // 104 ?int len = byteBuf.readableBytes(); //可讀的字節數 12System.out.println("len=" + len); ?//使用for取出各個字節for(int i = 0; i < len; i++) {System.out.println((char) byteBuf.getByte(i));} ?//按照某個范圍讀取System.out.println(byteBuf.getCharSequence(0, 4, Charset.forName("utf-8")));System.out.println(byteBuf.getCharSequence(4, 6, Charset.forName("utf-8")));}} }?
?
?
?
總結
以上是生活随笔為你收集整理的Netty之十大核心模块组件介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty之实现一个简单的群聊系统
- 下一篇: TCP的粘包和拆包及Netty中的解决方