我们在分析完initAndRegister方法之后,随后就进入了bind端口号的操作了。
abstract void init(Channel channel) throws Exception; private static void doBind0( final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) { // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up // the pipeline in its channelRegistered() implementation. // 这个方法会在channelRegistered方法被触发之前调用,?给自定义的handler机会去设置pipeline在它的
// channelRegistered实现中channel.eventLoop().execute(new Runnable() {//向当前的事件循环提交了一个任务,这个任务是在提交注册任务之后进行的,
//所以一定是注册有结果了才进行的下一个任务 @Override public void run() { if (regFuture.isSuccess()) { channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { promise.setFailure(regFuture.cause()); } } }); }
调用channel的bind方法
@Override public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { return pipeline.bind(localAddress, promise); }
再调用pipeline中的bind方法
@Override public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { return tail.bind(localAddress, promise);//在尾部的channelHandler的上下文对象的bind方法 }
tail中的bind方法
@Override public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) { if (localAddress == null) { throw new NullPointerException("localAddress"); } if (isNotValidPromise(promise, false)) { // cancelled return promise; } final AbstractChannelHandlerContext next = findContextOutbound(); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeBind(localAddress, promise); } else { safeExecute(executor, new Runnable() { @Override public void run() { next.invokeBind(localAddress, promise); } }, promise, null); } return promise; }
private void invokeBind(SocketAddress localAddress, ChannelPromise promise) { if (invokeHandler()) {//此时的handler已经完成了add方法的调用,返回true try { ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise); //因为一般的handler并没有对bind方法进行重写,只是继承父类的方法,直接将这个bind操作向下传递, //随着传递的进行,到了head的handler里面,而headhandler对它进行了处理, } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } } else { bind(localAddress, promise); } }
下面的head中的实现
@Override public void bind( ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception { unsafe.bind(localAddress, promise); }
unsafe的方法中关键的代码
boolean wasActive = isActive(); try { doBind(localAddress); } catch (Throwable t) { safeSetFailure(promise, t); closeIfClosed(); return; } if (!wasActive && isActive()) {//因为bind端口成功,channel处于活动状态,isActive将会返回true invokeLater(new Runnable() {//接着它又向io线程提交了一个任务,这个任务是在bind之后才执行的。 @Override public void run() { pipeline.fireChannelActive();//会通知在这个pipeline中的所有handler执行channelActive方法 //首当其冲的当然是我们head的handler了 }
我们看一下head中的handler回调
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelActive(); readIfIsAutoRead();//这个关键代码,会去重新设置Channel的感兴趣key }
private void readIfIsAutoRead() { if (channel.config().isAutoRead()) {//默认为true channel.read(); } }
@Override public final ChannelPipeline read() { tail.read(); return this; }
public ChannelHandlerContext read() { final AbstractChannelHandlerContext next = findContextOutbound(); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeRead(); } else { Runnable task = next.invokeReadTask; if (task == null) { next.invokeReadTask = task = new Runnable() { @Override public void run() { next.invokeRead(); } }; } executor.execute(task); } return this; }
private void invokeRead() { if (invokeHandler()) { try { ((ChannelOutboundHandler) handler()).read(this);//一般都会将这个方法往下传递,知道handler中有真正的处理 } catch (Throwable t) { notifyHandlerException(t); } } else { read(); } }
又回到了我们的head中
@Override public void read(ChannelHandlerContext ctx) { unsafe.beginRead(); }
@Override public final void beginRead() { assertEventLoop(); if (!isActive()) { return; } try { doBeginRead(); } catch (final Exception e) { invokeLater(new Runnable() { @Override public void run() { pipeline.fireExceptionCaught(e); } }); close(voidPromise()); } }最终来到了AbstractNioChannel
@Override protected void doBeginRead() throws Exception { // Channel.read() or ChannelHandlerContext.read() was called final SelectionKey selectionKey = this.selectionKey;//这个key就是我们刚开始注册0产生的key if (!selectionKey.isValid()) { return; } readPending = true; final int interestOps = selectionKey.interestOps(); if ((interestOps & readInterestOp) == 0) { selectionKey.interestOps(interestOps | readInterestOp);//利用我们初始化Channel时给定readInterestOp重新设置感兴趣key