下文将剖析ServerBootstrap.bindAsync()方法所涉及到的流程。
1.概念
ChannelHandler分ChannelUpstreamHandler和ChanneldownstreamHandler,前者指向服务器接收事件的调用处理器,后者是服务器由内而外发送事件的事件处理器。
上下行消息传递方法介绍
sendUpstream()方法表发由外向内传递事件,
public void sendUpstream(ChannelEvent e) {
DefaultChannelHandlerContext head = getActualUpstreamContext(this.head);
if (head == null) {
if (logger.isWarnEnabled()) {
logger.warn(
"The pipeline contains no upstream handlers; discarding: " + e);
}
return;
}
sendUpstream(head, e);
}
void sendUpstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
try {
((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
} catch (Throwable t) {
notifyHandlerException(e, t);
}
}
从处理器链最远的Head开始调用handleUpstream()方法。
sendDownstream方法负责从最里面开始向外发送事件。
public void sendDownstream(ChannelEvent e) {
DefaultChannelHandlerContext tail = getActualDownstreamContext(this.tail);
if (tail == null) {
try {
getSink().eventSunk(this, e);
return;
} catch (Throwable t) {
notifyHandlerException(e, t);
return;
}
}
sendDownstream(tail, e);
}
void sendDownstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
if (e instanceof UpstreamMessageEvent) {
throw new IllegalArgumentException("cannot send an upstream event to downstream");
}
try {
((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
} catch (Throwable t) {
e.getFuture().setFailure(t);
notifyHandlerException(e, t);
}
}
sendDownstream依次从内向外沿着处理器链进行传递,直到最后传递给ChannelSink,这个类是处理接收处理终端的下行事件。
bind操作分析:
1.新建事件处理器SimpleChannelUpstreamHandler子类binder,负责在收到Open事件后发出bind请求。
2.新建ChannelPipeline类bossPipeline,并将binder和parentHandler(如果有,用户指定处理器)依次添加到bossPipeline末尾
3.利用NioServerSocketChannelFactory,以bossPipeline为参数创建Channel。在其中的构造函数中
3.1.ServerSocketChannel.open();打开socket
3.2.fireChannelOpen()中channel.getPipeline().sendUpstream发送上行消息OPEN状态事件,以此事件为起始引发后续bind操作。
4.OPEN事件传递到binder后会调用其channelOpen()方法,该方法设置了相关Option,继续传递OPEN事件到下一个处理器parentHandler。最后调用channel.bind()方法绑定localAddress。
5.该绑定方法会调用sendDownstream()方法向下行流传递BOUND状态事件。binder为上行流处理器,忽略,parentHandler如果是对应处理器则调用。最后由NioServerSocketPipelineSink.eventSunk响应最终的下行流事件。NioServerSocketPipelineSink会调用NioServerBoss的bind()
6.该bind()会生成RegisterTask到任务队列中。
7.RegisterTask的任务
7.1.channel.socket.socket().bind绑定address
7.2.fireChannelBound把BOUND事件沿上行流传递,binder对此不处理。
7.3.channel.socket.register()将socket的OP_ACCEPT事件注册到selector上。
以上事件传递如下图所示:
至此,已完成服务器socket的绑定,并开始监听。