请看一下简单的 一个netty4服务端启动代码样例
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class); b.handler(new LoggingHandler(LogLevel.DEBUG)); b.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new echoServerHandler()); } }); b.option(ChannelOption.SO_KEEPALIVE, true); b.childOption(ChannelOption.SO_BACKLOG, 128); ChannelFuture channelFuture = b.bind(2000).sync(); channelFuture.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); System.out.println("called shutdown gracefully..."); }
大家看到了,
ChannelFuture channelFuture = b.bind(2000).sync();发生了什么调用呢 ?下面分析一下其调用链.首先上一个调用的轮廓图
上图是 netty4 bind()执行的时候的调用链.
下面看代码层面的调用 :
1.AbstractBootstrap
样例创建的ServerBootstrap 执行bind的时候,直接执行父类的bind() ,它本身没有自己的实现.
//AbstractBootstrap public ChannelFuture bind() { validate(); SocketAddress localAddress = this.localAddress; if (localAddress == null) { throw new IllegalStateException("localAddress not set"); } return doBind(localAddress); } //-------------------------- private ChannelFuture doBind(final SocketAddress localAddress) { final ChannelFuture regPromise = initAndRegister(); final Channel channel = regPromise.channel(); final ChannelPromise promise = channel.newPromise(); if (regPromise.isDone()) { doBind0(regPromise, channel, localAddress, promise); } else { regPromise.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { doBind0(future, channel, localAddress, promise); } }); } return promise; } //-------------------3-------------------------- 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. 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()); } } }); }
2.bootStrap的bind会调用大abstractChannel的bind方法
//AbstractChannel //- @Override public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { return pipeline.bind(localAddress, promise); }
3.abstractChannel会去调用 DefaultChannelPipeline的bind
///DefaultChannelPipeline @Override public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { return tail.bind(localAddress, promise); }
4.DefaultChannelPipeline就是channel的管道.因为bind属于out方法,因此调用管道顺序是 tail ->head (handler)
在调用tail的bind的时候 ,走到了 DefaultChannelHandlerContext的bind,请看
//DefaultChannelHandlerContext @Override public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) { if (localAddress == null) { throw new NullPointerException("localAddress"); } validatePromise(promise, false); final DefaultChannelHandlerContext next = findContextOutbound(); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeBind(localAddress, promise); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeBind(localAddress, promise); } }); } return promise; }
5.上面有一句 final DefaultChannelHandlerContext next = findContextOutbound(); 要找outbound事件执行bind
只有headHandler继承了outBoundHandler,这时候又走到了DefaultChannelHandlerContext 的 invokeBind
// DefaultChannelHandlerContext
private void invokeBind(SocketAddress localAddress, ChannelPromise promise) { try { ((ChannelOutboundHandler) handler).bind(this, localAddress, promise); } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } }
6.此时走到了 headhandler 的bind里面去了.(此时handler只有 tailHandler,headHeadler,ServerBootstrapAcceptor等几个.只有head属于outboundler)
//HeadHandler @Override public void bind( ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception { unsafe.bind(localAddress, promise); }
7.此时调用链走到了unsafe的bind里面.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(); }
8.unsafe属于AbstractChannel的内部类.因此doBind(localAddress)调用的就是AbstractChannel的子类NioServerSocketChannel的方法
//NioServerSocketChannel @Override protected void doBind(SocketAddress localAddress) throws Exception { javaChannel().socket().bind(localAddress, config.getBacklog()); }
//
@Override
protected ServerSocketChannel javaChannel() {
return (ServerSocketChannel) super.javaChannel();
}
//abstractNioChannel 可以看到 这个channle的来源是 java.nio.serverSocketChannel
protected SelectableChannel javaChannel() {
return ch;
}
此动作完成了 .bind方法的的所有bind操作.
原文:http://www.cnblogs.com/wangkaick/p/5107818.html