fifty-eight。 Netty source code analysis-ServerBootstrap bind process-1
一. 开始
接上一篇 ServerBootstrap的初始化
https://blog.51cto.com/483181/2119149
二. bind过程2.1 代码
先看下调用的源代码
public void bind(int port) throws Exception { ... try { ... ChannelFuture f = b.bind(port).sync(); //bind过程 ... } catch (Exception e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }2.2 bindpublic ChannelFuture bind(int inetPort) { return bind(new InetSocketAddress(inetPort)); }public ChannelFuture bind(SocketAddress localAddress) { validate(); if (localAddress == null) { throw new NullPointerException("localAddress"); } return doBind(localAddress);}
从上面代码可以看出几点:
bind方法逻辑很简单,经过一系列的判断后最后调用doBind()方法发现Netty代码里面,从外面调用进去后,内部方法一般用doxxx,xxx0这种命名;以前自己看安卓源代码的时候,安卓一般喜欢用xxxInner的命名。风格而已,也许自己以后写代码可以参考(看源代码除了了解原理外,学习别人的代码架构方法也是一种收获)。
继续看doBind
2.3 doBindprivate ChannelFuture doBind(final SocketAddress localAddress) { final ChannelFuture regFuture = initAndRegister(); //1. init和register final Channel channel = regFuture.channel(); if (regFuture.cause() != null) { return regFuture; } if (regFuture.isDone()) { // At this point we know that the registration was complete and successful. ChannelPromise promise = channel.newPromise(); doBind0(regFuture, channel, localAddress, promise); return promise; } else { // Registration future is almost always fulfilled already, but just in case it's not. final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); regFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { Throwable cause = future.cause(); if (cause != null) { // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an // IllegalStateException once we try to access the EventLoop of the Channel. promise.setFailure(cause); } else { // Registration was successful, so set the correct executor to use. // See https://github.com/netty/netty/issues/2586 promise.registered(); doBind0(regFuture, channel, localAddress, promise); } } }); return promise; } }
上面这一段代码包含的东西就比较多了,先来看 initAndRegister
2.4 initAndRegister
顾名思义,这个方法包含初始化和注册两个步骤,代码如下:
final ChannelFuture initAndRegister() { Channel channel = null; try { channel = channelFactory.newChannel(); init(channel); } catch (Throwable t) { ... } ChannelFuture regFuture = config().group().register(channel); if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } return regFuture; }
从上面代码,我们可以看到几点:
channel = channelFactory.newChannel();
channelFactory是什么?它的类型是ReflectiveChannelFactory,如果大家不记得了,可以看看上一篇channel设置那个地方。
https://blog.51cto.com/483181/2119149public B channel(Class, Object> e: attrs.entrySet()) { //设置attr属性 @SuppressWarnings("unchecked") AttributeKey key = (AttributeKey) e.getKey(); channel.attr(key).set(e.getValue()); } } ChannelPipeline p = channel.pipeline(); final EventLoopGroup currentChildGroup = childGroup; final ChannelHandler currentChildHandler = childHandler; final Entry, Object>[] currentChildAttrs; synchronized (childOptions) { currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size())); } synchronized (childAttrs) { currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); } p.addLast(new ChannelInitializer() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } ch.eventLoop().execute(new Runnable() { @Override public void run() { pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } }); }
先来看设置options
2.8 setOptionsfinal Map