ServerBootstrap是Netty中用于构建的服务器的引导类(辅助类),用于对服务器启动之前做一个配置,编程风格采用方法连的方式,优雅美观。
ServerBootstrap bootstrap = new ServerBootstrap();
EventLoopGroup parent = new NioEventLoopGroup();
EventLoopGroup child = new NioEventLoopGroup();
bootstrap.group(parent,child)//ServerBootstrap中的childGroup属性,以及超类AbstractBootstrap中group属性进行赋值
.channel(NioServerSocketChannel.class)//对超类AbstractBootstrap中的channelFactory属性进行赋值
.childHandler(new ChannelInitializer<Channel>() {//对ServerBootstrap中的childHandler属性进行赋值
@Override
protected void initChannel(Channel ch) throws Exception {
}
}).handler(null);对AbstractBootstrap中的handler属性进行赋值
下面我们对ServerBootstrap的bind()方法进行详细梳理:
查看源码,可以看出bind方法最关键的方法在于initAndRegister()方法:
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();//利用BootStrap中配置好的channelFactory根据Channel的类型实例化一个Channel.
init(channel);//初始化实例化后的channel
} catch (Throwable t) {
if (channel != null) {
// channel can be null if newChannel crashed (eg SocketException("too many open files"))
//channel是可以为空的,如果newChannel方法抛出异常了,例如SocketException
channel.unsafe().closeForcibly();
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
//当channel注册失败后,我们需要强制性的返回一个ChannelFuture,并设置标志值为failure
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
//当channel不能注册,我们需要的返回一个ChannelFuture,传入一个FailedChannel,并设置标志值为failure
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
//这里就将channel注册到EventLoop当中。下面有源码解析。
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
下面是init()方法的重要代码,用于给ChannelPipeline添加ChannelHandler.
/**
* 在channelpiple中添加可能存在的ChannelHandler
* 使用channel的eventloop(其实也是执行器excutor)执行一个任务,
* 任务的工作是给pipleline增加一个ServerBootstrapAcceptor的ChannelHandler,用于接收连接
*/
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
下面是initAndRegister()方法中将Channel注册到EventLoop中的源码解析
- 调用config()方法获得BootStrap中获得一个完整的配置信息对象,通过group()方法获取EventLoopGroup对象
- 调用group的register方法进行注册
@Override
public ChannelFuture register(Channel channel) {
//next()方法会获取group当中的某一个EventLoop,然后调用EventLoop的register()方法
return next().register(channel);
}
- 而我们在NioServerEventLoopGroup的时候,我们在给children赋予的EventLoop是NioEventLoop,所以将会调用NioEventLoop.register方法
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
public void register(final SelectableChannel ch, final int interestOps, final NioTask<?> task) {
//对一些值的判断,省略
try {
//这里就调用Java NIO中的API,用于注册该channel感兴趣的key
ch.register(selector, interestOps, task);
} catch (Exception e) {
throw new EventLoopException("failed to register a channel", e);
}
}