當需要引導客戶端或一些無連接協議時,需要使用Bootstrap類。 在本節中,我們將回顧可用的各種方法引導客戶端,引導線程,和可用的管道實現。
### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Bootstrapping%20clients%20and%20connectionless%20protocols.md#客戶端引導方法)客戶端引導方法
下表是 Bootstrap 的常用方法,其中很多是繼承自 AbstractBootstrap。
Table 9.1 Bootstrap methods
| 名稱 | 描述 |
| --- | --- |
| group | 設置 EventLoopGroup 用于處理所有的 Channel 的事件 |
| channel channelFactory | channel() 指定 Channel 的實現類。如果類沒有提供一個默認的構造函數,你可以調用 channelFactory() 來指定一個工廠類被 bind() 調用。 |
| localAddress | 指定應該綁定到本地地址 Channel。如果不提供,將由操作系統創建一個隨機的。或者,您可以使用 bind() 或 connect()指定localAddress |
| option | 設置 ChannelOption 應用于 新創建 Channel 的 ChannelConfig。這些選項將被 bind 或 connect 設置在通道,這取決于哪個被首先調用。這個方法在創建管道后沒有影響。所支持 ChannelOption 取決于使用的管道類型。請參考9.6節和 ChannelConfig 的 API 文檔 的 Channel 類型使用。 |
| attr | 這些選項將被 bind 或 connect 設置在通道,這取決于哪個被首先調用。這個方法在創建管道后沒有影響。請參考9.6節。 |
| handler | 設置添加到 ChannelPipeline 中的 ChannelHandler 接收事件通知。 |
| clone | 創建一個當前 Bootstrap的克隆擁有原來相同的設置。 |
| remoteAddress | 設置遠程地址。此外,您可以通過 connect() 指定 |
| connect | 連接到遠端,返回一個 ChannelFuture, 用于通知連接操作完成 |
| bind | 將通道綁定并返回一個 ChannelFuture,用于通知綁定操作完成后,必須調用 Channel.connect() 來建立連接。 |
### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Bootstrapping%20clients%20and%20connectionless%20protocols.md#如何引導客戶端)如何引導客戶端
Bootstrap 類負責創建管道給客戶或應用程序,利用無連接協議和在調用 bind() 或 connect() 之后。
下圖展示了如何工作
[](https://github.com/waylau/essential-netty-in-action/blob/master/images/Figure%209.2%20Bootstrap%20process.jpg)
1. 當 bind() 調用時,Bootstrap 將創建一個新的管道, 當 connect() 調用在 Channel 來建立連接
2. Bootstrap 將創建一個新的管道, 當 connect() 調用時
3. 新的 Channel
Figure 9.2 Bootstrap process
下面演示了引導客戶端,使用的是 NIO TCP 傳輸
Listing 9.1 Bootstrapping a client
~~~
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap(); //1
bootstrap.group(group) //2
.channel(NioSocketChannel.class) //3
.handler(new SimpleChannelInboundHandler<ByteBuf>() { //4
@Override
protected void channeRead0(
ChannelHandlerContext channelHandlerContext,
ByteBuf byteBuf) throws Exception {
System.out.println("Received data");
byteBuf.clear();
}
});
ChannelFuture future = bootstrap.connect(
new InetSocketAddress("www.manning.com", 80)); //5
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture)
throws Exception {
if (channelFuture.isSuccess()) {
System.out.println("Connection established");
} else {
System.err.println("Connection attempt failed");
channelFuture.cause().printStackTrace();
}
}
});
~~~
1. 創建一個新的 Bootstrap 來創建和連接到新的客戶端管道
2. 指定 EventLoopGroup
3. 指定 Channel 實現來使用
4. 設置處理器給 Channel 的事件和數據
5. 連接到遠端主機
注意 Bootstrap 提供了一個“流利”語法——示例中使用的方法(除了connect()) 由 Bootstrap 返回實例本身的引用鏈接他們。
### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Bootstrapping%20clients%20and%20connectionless%20protocols.md#兼容性)兼容性
Channel 的實現和 EventLoop 的處理過程在 EventLoopGroup 中必須兼容,哪些 Channel 是和 EventLoopGroup 是兼容的可以查看 API 文檔。經驗顯示,相兼容的實現一般在同一個包下面,例如使用NioEventLoop,NioEventLoopGroup 和 NioServerSocketChannel 在一起。請注意,這些都是前綴“Nio”,然后不會用這些代替另一個實現和另一個前綴,如“Oio”,也就是說 OioEventLoopGroup 和NioServerSocketChannel 是不相容的。
Channel 和 EventLoopGroup 的 EventLoop 必須相容,例如NioEventLoop、NioEventLoopGroup、NioServerSocketChannel是相容的,但是 OioEventLoopGroup 和 NioServerSocketChannel 是不相容的。從類名可以看出前綴是“Nio”的只能和“Nio”的一起使用。
*EventLoop 和 EventLoopGroup*
*記住,EventLoop 分配給該 Channel 負責處理 Channel 的所有操作。當你執行一個方法,該方法返回一個 ChannelFuture ,它將在 分配給 Channel 的 EventLoop 執行。*
*EventLoopGroup 包含許多 EventLoops 和分配一個 EventLoop 通道時注冊。我們將在15章更詳細地討論這個話題。*
清單9.2所示的結果,試圖使用一個 Channel 類型與一個 EventLoopGroup 兼容。
Listing 9.2 Bootstrap client with incompatible EventLoopGroup
~~~
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap(); //1
bootstrap.group(group) //2
.channel(OioSocketChannel.class) //3
.handler(new SimpleChannelInboundHandler<ByteBuf>() { //4
@Override
protected void channelRead0(
ChannelHandlerContext channelHandlerContext,
ByteBuf byteBuf) throws Exception {
System.out.println("Reveived data");
byteBuf.clear();
}
});
ChannelFuture future = bootstrap.connect(
new InetSocketAddress("www.manning.com", 80)); //5
future.syncUninterruptibly();
~~~
1. 創建新的 Bootstrap 來創建新的客戶端管道
2. 注冊 EventLoopGroup 用于獲取 EventLoop
3. 指定要使用的 Channel 類。通知我們使用 NIO 版本用于 EventLoopGroup , OIO 用于 Channel
4. 設置處理器用于管道的 I/O 事件和數據
5. 嘗試連接到遠端。當 NioEventLoopGroup 和 OioSocketChannel 不兼容時,會拋出 IllegalStateException 異常
IllegalStateException 顯示如下:
Listing 9.3 IllegalStateException thrown because of invalid configuration
~~~
Exception in thread "main" java.lang.IllegalStateException: incompatible event loop
type: io.netty.channel.nio.NioEventLoop
at
io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:5
71)
...
~~~
出現 IllegalStateException 的其他情況是,在 bind() 或 connect() 調用前 調用需要設置參數的方法調用失敗時,包括:
* group()
* channel() 或 channnelFactory()
* handler()
handler() 方法尤為重要,因為這些 ChannelPipeline 需要適當配置。 一旦提供了這些參數,應用程序將充分利用 Netty 的能力。
- Introduction
- 開始
- Netty-異步和數據驅動
- Netty 介紹
- 構成部分
- 關于本書
- 第一個 Netty 應用
- 設置開發環境
- Netty 客戶端/服務端 總覽
- 寫一個 echo 服務器
- 寫一個 echo 客戶端
- 編譯和運行 Echo 服務器和客戶端
- 總結
- Netty 總覽
- Netty 快速入門
- Channel, Event 和 I/O
- 什么是 Bootstrapping 為什么要用
- ChannelHandler 和 ChannelPipeline
- 近距離觀察 ChannelHandler
- 總結
- 核心功能
- Transport(傳輸)
- 案例研究:Transport 的遷移
- Transport API
- 包含的 Transport
- Transport 使用情況
- 總結
- Buffer(緩沖)
- Buffer API
- ByteBuf - 字節數據的容器
- 字節級別的操作
- ByteBufHolder
- ByteBuf 分配
- 總結
- ChannelHandler 和 ChannelPipeline
- ChannelHandler 家族
- ChannelPipeline
- ChannelHandlerContext
- 總結
- Codec 框架
- 什么是 Codec
- Decoder(解碼器)
- Encoder(編碼器)
- 抽象 Codec(編解碼器)類
- 總結
- 提供了的 ChannelHandler 和 Codec
- 使用 SSL/TLS 加密 Netty 程序
- 構建 Netty HTTP/HTTPS 應用
- 空閑連接以及超時
- 解碼分隔符和基于長度的協議
- 編寫大型數據
- 序列化數據
- 總結
- Bootstrap 類型
- 引導客戶端和無連接協議
- 引導服務器
- 從 Channel 引導客戶端
- 在一個引導中添加多個 ChannelHandler
- 使用Netty 的 ChannelOption 和屬性
- 關閉之前已經引導的客戶端或服務器
- 總結
- 引導
- Bootstrap 類型
- 引導客戶端和無連接協議
- 引導服務器
- 從 Channel 引導客戶端
- 在一個引導中添加多個 ChannelHandler
- 使用Netty 的 ChannelOption 和屬性
- 關閉之前已經引導的客戶端或服務器
- 總結
- NETTY BY EXAMPLE
- 單元測試
- 總覽
- 測試 ChannelHandler
- 測試異常處理
- 總結
- WebSocket
- WebSocket 程序示例
- 添加 WebSocket 支持
- 測試程序
- 總結
- SPDY
- SPDY 背景
- 示例程序
- 實現
- 啟動 SpdyServer 并測試
- 總結
- 通過 UDP 廣播事件
- UDP 基礎
- UDP 廣播
- UDP 示例
- EventLog 的 POJO
- 寫廣播器
- 寫監視器
- 運行 LogEventBroadcaster 和 LogEventMonitor
- 總結
- 高級主題
- 實現自定義的編解碼器
- 編解碼器的范圍
- 實現 Memcached 編解碼器
- 了解 Memcached 二進制協議
- Netty 編碼器和解碼器
- 測試編解碼器
- EventLoop 和線程模型
- 線程模型的總覽
- EventLoop
- EventLoop
- I/O EventLoop/Thread 分配細節
- 總結
- 用例1:Droplr Firebase 和 Urban Airship
- 用例2:Facebook 和 Twitter