上一章介绍了 bind的逻辑.bind执行之后,会开启监听.今天讨论一下监听 bind到端口之后,开启监听这一段逻辑
1.首先从abstractUnsafe开始说起.可以看到,执行了dobind操作之后,紧接着执行的是
pipeline.fireChannelActive();
//abstractUnsafe
@Override public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { if (!ensureOpen(promise)) { return; } // See: https://github.com/netty/netty/issues/576 if (!PlatformDependent.isWindows() && !PlatformDependent.isRoot() && Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress()) { // Warn a user about the fact that a non-root user can‘t receive a // broadcast packet on *nix if the socket is bound on non-wildcard address. logger.warn( "A non-root user can‘t receive a broadcast packet if the socket " + "is not bound to a wildcard address; binding to a non-wildcard " + "address (" + localAddress + ") anyway as requested."); } boolean wasActive = isActive(); try { doBind(localAddress); } catch (Throwable t) { closeIfClosed(); promise.setFailure(t); return; } if (!wasActive && isActive()) { invokeLater(new Runnable() { @Override public void run() { pipeline.fireChannelActive(); } }); } promise.setSuccess(); }
2.fireChannelActive 会执行 DefaultChannelPipeline的fireChannelActive方法.这里面有两个事件 一个是inbound的 以后是outbound的
@Override public ChannelPipeline fireChannelActive() { head.fireChannelActive(); //inbound if (channel.config().isAutoRead()) { channel.read();//outbound } return this; }
3.先看head的inbound事件.其实没有做什么.inbound在当前所有handler(head,tail,accecptor)中只有head继承了inbound.head里面的channelActive是一个空实现.
//DefaultChannelHandlerContext @Override public ChannelHandlerContext fireChannelActive() { final DefaultChannelHandlerContext next = findContextInbound(); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeChannelActive(); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeChannelActive(); } }); } return this; } //----2---- private void invokeChannelActive() { try { ((ChannelInboundHandler) handler).channelActive(this); } catch (Throwable t) { notifyHandlerException(t); } } //TailHandler @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { }
4.再看一下第二个事件,read. 他直接调用AbstractChannel的read,然后走到DefaultChannelPipeline的read,然后到DefaultChannelHandlerContext的read
然后走到了HeadHandler的read.最后终于到了AbstractUnsafe的beginRead方法里面.
//AbstractChannel @Override public Channel read() { pipeline.read(); return this; } //DefaultChannelPipeline @Override public ChannelPipeline read() { tail.read(); return this; } ///DefaultChannelHandlerContext @Override public ChannelHandlerContext read() { final DefaultChannelHandlerContext 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; } //---2--------- private void invokeRead() { try { ((ChannelOutboundHandler) handler).read(this); } catch (Throwable t) { notifyHandlerException(t); } } //HeadHandler @Override public void read(ChannelHandlerContext ctx) { unsafe.beginRead(); } //AbstractUnsafe @Override public void beginRead() { if (!isActive()) { return; } try { doBeginRead(); } catch (final Exception e) { invokeLater(new Runnable() { @Override public void run() { pipeline.fireExceptionCaught(e); } }); close(voidPromise()); } }
5.doBeginRead调用的是 AbstractNioChannel的实现.
//AbstractNioChannel
@Override protected void doBeginRead() throws Exception { if (inputShutdown) { return; } final SelectionKey selectionKey = this.selectionKey; if (!selectionKey.isValid()) { return; } final int interestOps = selectionKey.interestOps(); if ((interestOps & readInterestOp) == 0) { selectionKey.interestOps(interestOps | readInterestOp); } }
6.最后一步
selectionKey.interestOps()的值是之前AbastractUnsafe类中的doRegister方法执行如下代码selectionKey = javaChannel().register(eventLoop().selector, 0, this)时设置的,因此值为0。
而readInterestOp是之前创建NioServerSocketChanne时,NioServerSocketChannel类的构造函数中设置的super(null, newSocket(), SelectionKey.OP_ACCEPT),因此值为16。
selectionKey.interestOps(interestOps | readInterestOp)会将ops设置为16。
也就是等待 连接过来的状态了.
原文:http://www.cnblogs.com/wangkaick/p/5107896.html