服务端channel的初始化大致分为以下几个步骤:
1、设置channelOptions,channelAttrs
2、设置childOptions,childAttrs
3、配置服务端pipeline:config handler
4、添加连接器,add serverBootstrapAcceptor,以后新的请求的都通过这个连接器处理。
首先,我们在上一篇文章的AbstractBootstrap的initAndRegister方法里面找到init(channel)这个函数,从这里开始,
现在分析的是服务端的,所以实现是ServerBootstrap的实现:
@Override
void init(Channel channel) throws Exception {
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
channel.config().setOptions(options);
}
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}
ChannelPipeline p = channel.pipeline();
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
}
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
}
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
// We add this handler via the EventLoop as the user may have used a ChannelInitializer as handler.
// In this case the initChannel(...) method will only be called after this method returns. Because
// of this we need to ensure we add our handler in a delayed fashion so all the users handler are
// placed in front of the ServerBootstrapAcceptor.
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
设置channelOptions,channelAttrs
这里的实现很简单,就是把传进来的数据options 和attrs放到map里面:
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
channel.config().setOptions(options);
}
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}
这这里需要说明的是,我们的用户代码没有设置options。
设置childOptions,childAttrs
childOptions和childAttrs是新的链接进来之后,我们需要给她设置的属性,而上面一个设置是服务端自己的属性。
用户的代码在这里设置:
.childOption(ChannelOption.TCP_NODELAY, true)
.childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue")
点进去看其中一个的实现:
public <T> ServerBootstrap childAttr(AttributeKey<T> childKey, T value) {
if (childKey == null) {
throw new NullPointerException("childKey");
}
if (value == null) {
childAttrs.remove(childKey);
} else {
childAttrs.put(childKey, value);
}
return this;
}
而这个childAttrs又是一个hashMap:
private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
在ServerBootstrap里面,我们这一步也是简单的复制了一下这两个hashMap:
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
}
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
}
简单。
配置服务端pipeline:config handler
后面有一段代码:
ChannelHandler handler = config.handler();
就是配置服务端pipeline。
添加连接器,add ServerBootstrapAcceptor
这一步是最重要的,以后我们新的请求都会经过它来初始化,就是这一句:
pipeline.addLast(new ServerBootstrapAcceptor(
currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
我们一个个分析参数:
currentChildGroup:
这是从childGroup来的,然后我们用户端代码有一段:b.group(bossGroup, workerGroup),点进去看,这个workerGroup就是我们ServerBootstrap的childGroup:
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
currentChildHandler:
这个其实也是从下面的用户代码进来的:
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new AuthHandler());
//..
}
});
currentChildOptions, currentChildAttrs:
这个就是我们上面第二步添加的childOptions和childAttrs
初始化比较简单,重点在最后一步添加连接器ServerBootstrapAcceptor。