Bootstrap類可以用來引導(dǎo)客戶端和一些無連接協(xié)議,在本節(jié)中,我們將回顧可用的各種方法引導(dǎo)客戶端,引導(dǎo)線程,和可用的管道實(shí)現(xiàn)。
下表是 Bootstrap 的常用方法,其中很多是繼承自 AbstractBootstrap。
Table 9.1 Bootstrap methods
名稱 | 描述 |
---|---|
group | 設(shè)置 EventLoopGroup 用于處理所有的 Channel 的事件 |
channel channelFactory | channel() 指定 Channel 的實(shí)現(xiàn)類。如果類沒有提供一個默認(rèn)的構(gòu)造函數(shù),你可以調(diào)用 channelFactory() 來指定一個工廠類被 bind() 調(diào)用。 |
localAddress | 指定應(yīng)該綁定到本地地址 Channel。如果不提供,將由操作系統(tǒng)創(chuàng)建一個隨機(jī)的。或者,您可以使用 bind() 或 connect()指定localAddress |
option | 設(shè)置 ChannelOption 應(yīng)用于 新創(chuàng)建 Channel 的 ChannelConfig。這些選項(xiàng)將被 bind 或 connect 設(shè)置在通道,這取決于哪個被首先調(diào)用。這個方法在創(chuàng)建管道后沒有影響。所支持 ChannelOption 取決于使用的管道類型。請參考9.6節(jié)和 ChannelConfig 的 API 文檔 的 Channel 類型使用。 |
attr | 這些選項(xiàng)將被 bind 或 connect 設(shè)置在通道,這取決于哪個被首先調(diào)用。這個方法在創(chuàng)建管道后沒有影響。請參考9.6節(jié)。 |
handler | 設(shè)置添加到 ChannelPipeline 中的 ChannelHandler 接收事件通知。 |
clone | 創(chuàng)建一個當(dāng)前 Bootstrap的克隆擁有原來相同的設(shè)置。 |
remoteAddress | 設(shè)置遠(yuǎn)程地址。此外,您可以通過 connect() 指定 |
connect | 連接到遠(yuǎn)端,返回一個 ChannelFuture, 用于通知連接操作完成 |
bind | 將通道綁定并返回一個 ChannelFuture,用于通知綁定操作完成后,必須調(diào)用 Channel.connect() 來建立連接。 |
Bootstrap 類負(fù)責(zé)創(chuàng)建管道給客戶或應(yīng)用程序,利用無連接協(xié)議和在調(diào)用 bind() 或 connect() 之后。
下圖展示了如何工作
Figure 9.2 Bootstrap process
下面演示了引導(dǎo)客戶端,使用的是 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();
}
}
});
注意 Bootstrap 提供了一個“流利”語法——示例中使用的方法(除了connect()) 由 Bootstrap 返回實(shí)例本身的引用鏈接他們。
Channel 的實(shí)現(xiàn)和 EventLoop 的處理過程在 EventLoopGroup 中必須兼容,哪些 Channel 是和 EventLoopGroup 是兼容的可以查看 API 文檔。經(jīng)驗(yàn)顯示,相兼容的實(shí)現(xiàn)一般在同一個包下面,例如使用NioEventLoop,NioEventLoopGroup 和 NioServerSocketChannel 在一起。請注意,這些都是前綴“Nio”,然后不會用這些代替另一個實(shí)現(xiàn)和另一個前綴,如“Oio”,也就是說 OioEventLoopGroup 和NioServerSocketChannel 是不相容的。
Channel 和 EventLoopGroup 的 EventLoop 必須相容,例如NioEventLoop、NioEventLoopGroup、NioServerSocketChannel是相容的,但是 OioEventLoopGroup 和 NioServerSocketChannel 是不相容的。從類名可以看出前綴是“Nio”的只能和“Nio”的一起使用。
EventLoop 和 EventLoopGroup
記住,EventLoop 分配給該 Channel 負(fù)責(zé)處理 Channel 的所有操作。當(dāng)你執(zhí)行一個方法,該方法返回一個 ChannelFuture ,它將在 分配給 Channel 的 EventLoop 執(zhí)行。
EventLoopGroup 包含許多 EventLoops 和分配一個 EventLoop 通道時注冊。我們將在15章更詳細(xì)地討論這個話題。
清單9.2所示的結(jié)果,試圖使用一個 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();
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)
...
出現(xiàn) IllegalStateException 的其他情況是,在 bind() 或 connect() 調(diào)用前 調(diào)用需要設(shè)置參數(shù)的方法調(diào)用失敗時,包括:
handler() 方法尤為重要,因?yàn)檫@些 ChannelPipeline 需要適當(dāng)配置。 一旦提供了這些參數(shù),應(yīng)用程序?qū)⒊浞掷?Netty 的能力。
更多建議: