Bootstrap是通道初始化辅助类 提供了初始化通道或子通道所需要的数据结构,那么ClientBootstrap就是客户端的,而且会执行连接操作。
配置通道,就是把相应的键值对选项传递给底层:
ClientBootstrap b = ...;
// Options for a new channel
b.setOption("remoteAddress", new InetSocketAddress("example.com", 8080));
b.setOption("tcpNoDelay", true);
b.setOption("receiveBufferSize", 1048576);
配置通道流水线,每个通道有自己的pipeline,建议的方式是调用Bootstrap.setPipelineFactory(ChannelPipelineFactory)来制定ChannelPipelineFactory :
ClientBootstrap b = ...;
b.setPipelineFactory(new MyPipelineFactory());
public class MyPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create and configure a new pipeline for a new channel.
ChannelPipeline p = Channels.pipeline();
p.addLast("encoder", new EncodingHandler());
p.addLast("decoder", new DecodingHandler());
p.addLast("logic", new LogicHandler());
return p;
}
}
另一种方式,只在特定情况下适用(在Bootstrap的源码中有解释),就是利用默认的pipeline,并且让新的Channel来浅拷贝它:
ClientBootstrap b = ...;
ChannelPipeline p = b.getPipeline();
// Add handlers to the default pipeline.
p.addLast("encoder", new EncodingHandler());
p.addLast("decoder", new DecodingHandler());
p.addLast("logic", new LogicHandler());
浅拷贝意味着默认pipeline里面的Handler,只是他们的引用增加到了新的ChannelPipeline中,所以要注意那些Handler是否有副作用。所以不适合在服务器端为每个新来的连接打开一个Channel的情况,为不同的Channel定制不同的配置。
此外ClientBootstrap只是一个辅助类,没有分配和管理任何资源,真正管理资源的是构造器中传入的ChannelFactory的实现,所以用同样的ChannelFactory 来构造多个Bootstrap实例,为不同的通道应用不同的设置是完全OK的。
bind方法: 绑定操作,在绑定和连接需要分开的时候用到。 比如在尝试连接之前,可以通过Channel.setAttachment(Object)为这个通道设置一个attachment 这样一旦连接建议,就可以访问这个attachment。
ChannelFuture bindFuture = bootstrap.bind(new InetSocketAddress("192.168.0.15", 0));
Channel channel = bindFuture.getChannel();
channel.setAttachment(dataObj);
channel.connect(new InetSocketAddress("192.168.0.30", 8080));
在ChannelHandler中可以向下面这样访问。
public class YourHandler extends SimpleChannelUpstreamHandler {
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
Object dataObject = ctx.getChannel().getAttachment();
}
}
详细的源码注释可以看我的Github。