Netty源码(三)之ServerBootstrap的bind(一)的过程

在前两篇博客中我们分别介绍了NioEventLoopGroup的创建过程ServerBootstarp的创建的过程前面的准备的过程都已经结束了。是时候启动我们的服务端了,打开我们熟悉的代码,具体的代码如下:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
//服务端
public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        //就是一个死循环,不停地检测IO事件,处理IO事件,执行任务
        //创建一个线程组:接受客户端连接   主线程
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);//cpu核心数*2
        //创建一个线程组:接受网络操作   工作线程
        EventLoopGroup workerGroup = new NioEventLoopGroup();  //cpu核心数*2
        //是服务端的一个启动辅助类,通过给他设置一系列参数来绑定端口启动服务
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        // 我们需要两种类型的人干活,一个是老板,一个是工人,老板负责从外面接活,
        // 接到的活分配给工人干,放到这里,bossGroup的作用就是不断地accept到新的连接,将新的连接丢给workerGroup来处理
        serverBootstrap.group(bossGroup, workerGroup)
                //设置使用NioServerSocketChannel作为服务器通道的实现
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 128) //设置线程队列中等待连接的个数
                .childOption(ChannelOption.SO_KEEPALIVE, true)//保持活动连接状态
                //表示服务器启动过程中,需要经过哪些流程,这里NettyTestHandler最终的顶层接口为ChannelHandler,
                // 是netty的一大核心概念,表示数据流经过的处理器
                .handler(new NettyTestHendler())
                //表示一条新的连接进来之后,该怎么处理,也就是上面所说的,老板如何给工人配活
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        nioSocketChannel.pipeline().addLast(new StringDecoder(), new NettyServerHendler());
                    }
                });
        System.out.println(".........server  init..........");
        // 这里就是真正的启动过程了,绑定9090端口,等待服务器启动完毕,才会进入下行代码
        ChannelFuture future = serverBootstrap.bind(9090).sync();
        System.out.println(".........server start..........");
        //等待服务端关闭socket
        future.channel().closeFuture().sync();
        // 关闭两组死循环
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

今天我们主要分析的是serverBootstrap.bind(9090)方法,让我们点开对应的源码,一探究竟,看看服务端是如何启动,具体的代码如下:

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
	public ChannelFuture bind(int inetPort) {
    		//根据传入的端口号,创建一个本地的IP地址+端口号传入到bind()方法中去
        return bind(new InetSocketAddress(inetPort));
    }
  public ChannelFuture bind(SocketAddress localAddress) {
        //判断 group channelFactory 对象不为空    serverBootstrap.group    serverBootstrap.channel  已经设置
        validate();
        //ObjectUtil.checkNotNull(localAddress, "localAddress") 还是返回的localAddress对象  判断不为空
    		//继续调用diBind()方法
        return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
    }
  //这儿校验对应的group和channelFactory是否已经设置好
  public B validate() {
    		//group是NioEventLoopGroup,就是我们上篇博客中提到的有很多属性的对象
        if (group == null) {
            throw new IllegalStateException("group not set");
        }
    		//channelFactory对应的NioServerSocketChannel.class的工厂类,对应的有两个参数,上篇博客也有说到
        if (channelFactory == null) {
            throw new IllegalStateException("channel or channelFactory not set");
        }
        return self();
    }
  //这个方法就是整个服务端启动的流程,我们要一点点的分析
  private ChannelFuture doBind(final SocketAddress localAddress) {
        //初始化和注册
    		//走来进入的initAndRegister()的方法
        final ChannelFuture regFuture = initAndRegister();
        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) {
                        promise.setFailure(cause);
                    } else {
                        promise.registered();
                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
            });
            return promise;
        }
    }
}

上面的方法,就是绑定了一个IP地址+端口号,同时进行相应的校验,校验groupchannelFactory是否为空,因为我们前面已经设置了,所以这儿不可能为空,所以调用对应doBind()方法,当打开对应的方法,发现方法很长,所以我们这儿要一点点到分析,走来执行的initAndRegister();方法。我们打开对应的代码,如下:

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
  final ChannelFuture initAndRegister() {
          Channel channel = null;
          try {
              //通过反射创建NioServerSocketChannel
              //channelFactory=new ReflectiveChannelFactory  ---> constructor=NioServerSocketChannel.class.getConstructor();
              //channel=NioServerSocketChannel
            	//走来先调用channelFactory.newChannel();的方法
              channel = channelFactory.newChannel();
              init(channel);
          } catch (Throwable t) {
              if (channel != null) {
                  channel.unsafe().closeForcibly();
                  return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
              }
              return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
          }
          //config().group()==bossGroup  ===> EventLoopGroup bossGroup=new NioEventLoopGroup(1);
          //register开启了事件轮询线程
          //config().group()  boosGroup
          ChannelFuture regFuture = config().group().register(channel);
          if (regFuture.cause() != null) {
              if (channel.isRegistered()) {
                  channel.close();
              } else {
                  channel.unsafe().closeForcibly();
              }
          }
          return regFuture;
      }
}

上面的代码我们发现走来的调用channelFactory.newChannel();的方法,我们在上一篇博客讲ServerBootstrap初始化的过程的时候,我们知道这个channelFactory属性对应的NioServerSocketChannel.class.getConstructor(),而newChannel()就是调用NioServerSocketChannel的构造函数,我们打开对应类的构造函数,具体的代码如下:

public class NioServerSocketChannel extends AbstractNioMessageChannel
                             implements io.netty.channel.socket.ServerSocketChannel {
	public NioServerSocketChannel() {
        //newSocket(DEFAULT_SELECTOR_PROVIDER)返回 ServerSocketChannel
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }
  //创建的是java nio中ServerSocketChannel
  private static ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            /**
             *  使用{@link SelectorProvider}打开{@link SocketChannel},从而删除条件in
             *  否则,每个ServerSocketChannel.open()将调用{@link SelectorProvider#provider()}。
             *
             *  See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
             */
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException(
                    "Failed to open a server socket.", e);
        }
    }
  public NioServerSocketChannel(ServerSocketChannel channel) {
    		//调用对应的父类的构造函数
        super(null, channel, SelectionKey.OP_ACCEPT);
        //javaChannel()==>  serverSocketChannel
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }
}

我们发现调用NioServerSocketChannel的构造函数函数,创建了一个java原生的ServerSocketChannel,然后调用父类的构造函数,我们继续跟进去,查看对应的代码,具体的代码如下:

public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
  //传入进来的parent = null
  //ch = java 原生的ServerSocketChannel
  //readInterestOp = SelectionKey.OP_ACCEPT 注册事件
  protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        //parent -->  null
        //ch--> serverSocketChannel  服务端channel
        //readInterestOp--->SelectionKey.OP_ACCEPT
    		//调用对应的父类的构造函数
        super(parent, ch, readInterestOp);
    }
}

当我们打开对应的函数发现调用的是父类的对应的构造函数,所以我们继续跟进父类的构造函数,打开对应的构造函数如下:

public abstract class AbstractNioChannel extends AbstractChannel {
	protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        //parent ---> null
        //ch ---> serverSocketChannel  服务器channel java 原生的ServerSocketChannel
        //readInterestOp ---> SelectionKey.OP_ACCEPT 注册事件
    		//继续调用对应的父类的构造函数
        super(parent);
        this.ch = ch;
        this.readInterestOp = readInterestOp;
        try {
            ch.configureBlocking(false);
        } catch (IOException e) {
            try {
                ch.close();
            } catch (IOException e2) {
                if (logger.isWarnEnabled()) {
                    logger.warn(
                            "Failed to close a partially initialized socket.", e2);
                }
            }
            throw new ChannelException("Failed to enter non-blocking mode.", e);
        }
    }
}

当我们打开父类的构造函数,发现调用的还是父类的构造函数,我们继续打开对应的父类的构造函数,具体代码如下:

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
	protected AbstractChannel(Channel parent) {
        //parent = null
        this.parent = parent;
        id = newId();
        //读写都和这个对象有关
        unsafe = newUnsafe();
    		//创建对应的ChannelPipeline()
        pipeline = newChannelPipeline();
    }
}

我们发现打开对应的父类的构造函数,主要操作时对parent进行对应的赋值,然后创建id进行对应的赋值,unsafe和pipeline同样时进行创建赋值。我们先打开newId()对应的代码如下:

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
	protected ChannelId newId() {
        return DefaultChannelId.newInstance();
    }
}

当我们打开对应的创建ID的方法,发现是继续调用对应的创建ID的函数,最终点进去,我们发现就是随机生成ID。至于生成规则我们不需要做过多的了解。你只需要知道这个ID是用来作为channel的标示字段,具有唯一性,有点像数据库中的主键。我们看完了创建ID的过程,我们继续查看创建Unsafe接口的实现类的过程。由于Unsafe接口的实现类的过程比较复杂,我们就查看一下Unsafe接口中的方法,打开对应的代码如下:

interface Unsafe {
  			//当接收到数据,将用于分配ByteBuf
        RecvByteBufAllocator.Handle recvBufAllocHandle();
 			 	//返回绑定到本地的socketAddress,如果没有则返回null
        SocketAddress localAddress();
  			//返回绑定到远程的socketAddress,如果没有则返回null
        SocketAddress remoteAddress();
  			//注册ChannelPromise的Channel,并在注册完成后通知ChannelFuture
        void register(EventLoop eventLoop, ChannelPromise promise);
  			//将SocketAddress绑定到ChannelPromise的Channel,并在完成后通知
        void bind(SocketAddress localAddress, ChannelPromise promise);
  			//将给定的ChannelFuture的Channel与给定的远程SocketAddress连接。 
  			//如果应使用特定的本地SocketAddress,则需要将其作为参数。否则,只需
  			//将null传递给它。连接操作完成后,ChannelPromise将会收到通知。
        void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
  			//操作完成后,断开ChannelFuture的Channel并通知ChannelPromise
        void disconnect(ChannelPromise promise);
  			//操作完成后,关闭ChannelPromise的Channel并通知ChannelPromise
        void close(ChannelPromise promise);
  			//立即关闭Channel而不触发任何事件。可能仅在注册尝试失败时有用。
        void closeForcibly();
  			//从EventLoop中注销ChannelPromise的Channel,并在操作完成后通知ChannelPromise
        void deregister(ChannelPromise promise);
  			//调度读取操作,该操作将填充ChannelPipeline中第一个ChannelInboundHandler的入站缓冲区。
  			//如果已经有一个待处理的读取操作,则此方法不执行任何操作。
        void beginRead();
  			//写操作
        void write(Object msg, ChannelPromise promise);
  			//清除通过ChannelPromise安排的所有写操作。
        void flush();
  			//返回一个特殊的ChannelPromise,可以重复使用并将其传递给Unsafe中的操作。
  			//永远不会通知它成功或错误,所以它只是一个占位符以ChannelPromise为参数但您不想被通知的操作。
        ChannelPromise voidPromise();
  			//返回Channel的ChannelOutboundBuffer,存储未决的写请求。
        ChannelOutboundBuffer outboundBuffer();
    }

可以看到Unsafe接口的类主要处理的读写,一些连接的事件的处理。看完了unsafe属性的赋值,最后让我们看看创建pipeline的过程,具体代码如下:

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
	protected AbstractChannel(Channel parent) {
        //parent = null
        this.parent = parent;
        id = newId();
        //读写都和这个对象有关
        unsafe = newUnsafe();
    		//创建对应的ChannelPipeline()
        pipeline = newChannelPipeline();
    }
}

我们去查看对应的pipeline的创建过程。具体的代码如下:

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
	protected DefaultChannelPipeline newChannelPipeline() {
        //this-->NioServerSocketChannel
        return new DefaultChannelPipeline(this);
    }
}

我们可以看到调用的DefaultChannelPipeline的构造函数,传入的参数是NioServerSocketChannel这个时候我们打开DefaultChannelPipeline的构造函数,具体的代码如下:

public class DefaultChannelPipeline implements ChannelPipeline {
  //传入的参数是NioServerSocketChannel
  protected DefaultChannelPipeline(Channel channel) {
        this.channel = ObjectUtil.checkNotNull(channel, "channel");
        succeededFuture = new SucceededChannelFuture(channel, null);
        voidPromise =  new VoidChannelPromise(channel, true);
        //创建尾结点
        tail = new TailContext(this);
        //创建头节点   头节点中维护了AbstractChannel中unsafe对象
        head = new HeadContext(this);
        head.next = tail;
        tail.prev = head;
    }
}

可以发现上面的代码就是进行对应的赋值操作,赋值完的DefaultChannelPipeline如下图所示:

在这里插入图片描述

创建好的DefaultChannelPipeline的对象如上图所示,我们再来看看TailContextHeadContext的创建过程,具体的代码如下:

final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler {
  TailContext(DefaultChannelPipeline pipeline) {
    //调用父类的构造函数
    super(pipeline, null, TAIL_NAME, TailContext.class);
    //设置添加完成
    setAddComplete();
  }
}
final class HeadContext extends AbstractChannelHandlerContext
            implements ChannelOutboundHandler, ChannelInboundHandler {
  private final Unsafe unsafe;
  HeadContext(DefaultChannelPipeline pipeline) {
    //调用父类的构造函数
    super(pipeline, null, HEAD_NAME, HeadContext.class);
    unsafe = pipeline.channel().unsafe();
    //设置添加完成
    setAddComplete();
  }
}

两个对象的创建都是调用父类的构造函数,具体的代码如下:

abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
  AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class<? extends ChannelHandler> handlerClass) {
        //pipeline=DefaultChannelPipeline
        //executor=null
        //name =没传系统默认创建
        //handler=TailContext.class
        this.name = ObjectUtil.checkNotNull(name, "name");
        this.pipeline = pipeline;
        this.executor = executor;
        this.executionMask = mask(handlerClass);
        ordered = executor == null || executor instanceof OrderedEventExecutor;
    }
}

创建好的AbstractChannelHandlerContext如下图所示:

在这里插入图片描述

我们执行AbstractChannelHandlerContext创建完成后,我们通过CAS设置成添加完成了。至此newChannelPipeline()创建完成了,最后我们再看下对应的代码,具体如下:

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
	protected AbstractChannel(Channel parent) {
        //parent = null
        this.parent = parent;
        id = newId();
        //读写都和这个对象有关
        unsafe = newUnsafe();
    		//创建对应的ChannelPipeline()
        pipeline = newChannelPipeline();
    }
}

至此AbstractChannel类创建完成,具体的AbstractChannel类如下图所示:

在这里插入图片描述

父类AbstractChannel创建完成了,我们回到AbstractNioChannel继续执行下面的代码,具体的代码如下:

public abstract class AbstractNioChannel extends AbstractChannel {
	protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        //parent -->  null
        //ch--> serverSocketChannel  服务器channel
        //readInterestOp--->SelectionKey.OP_ACCEPT
        //创建id,unsafe pipeline
    		//执行完父类的构造函数返回了,继续往下执行赋值操作
        super(parent);
        this.ch = ch;
        this.readInterestOp = readInterestOp;
        try {
          	//设置成非阻塞
            ch.configureBlocking(false);
        } catch (IOException e) {
            try {
                ch.close();
            } catch (IOException e2) {
                if (logger.isWarnEnabled()) {
                    logger.warn(
                            "Failed to close a partially initialized socket.", e2);
                }
            }
            throw new ChannelException("Failed to enter non-blocking mode.", e);
        }
    }
}

这个时候AbstractNioChannel类的图如下所示:

在这里插入图片描述

这个时候AbstractNioChannel初始化完成了,返回到原来的调用的地方,具体的代码如下:

public class NioServerSocketChannel extends AbstractNioMessageChannel
                             implements io.netty.channel.socket.ServerSocketChannel {
	public NioServerSocketChannel(ServerSocketChannel channel) {
    		//调用完成后返回,继续执行下面的代码
        super(null, channel, SelectionKey.OP_ACCEPT);
        //javaChannel()==>  serverSocketChannel
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }
}

可以看到我们又创建了一个对象NioServerSocketChannelConfig(this, javaChannel().socket());传入的参数的当前对象,和javaChannel().socket()两个参数,由于是同样是赋值操作,我直接在下面用代码表示

public class NioServerSocketChannel extends AbstractNioMessageChannel
                             implements io.netty.channel.socket.ServerSocketChannel {
	private final class NioServerSocketChannelConfig extends DefaultServerSocketChannelConfig {
        private NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) {
            // channel  --> NioServerSocketChannel
            //javaSocket==>  serverSocketChannel.socket()  服务端channel  nio  api
          	//一样调用的是父类的构造函数
            super(channel, javaSocket);
        }
  }
}

public class DefaultServerSocketChannelConfig extends DefaultChannelConfig
                                              implements ServerSocketChannelConfig {
	public DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) {
        // channel  --> NioServerSocketChannel
        //javaSocket==>  serverSocketChannel.socket()  服务端channel  nio  api
    		//一样调用的是父类的构造函数进行赋值
        super(channel);
        if (javaSocket == null) {
            throw new NullPointerException("javaSocket");
        }
        this.javaSocket = javaSocket;
    }
}

public class DefaultChannelConfig implements ChannelConfig {
	public DefaultChannelConfig(Channel channel) {
        // channel  --> NioServerSocketChannel
        this(channel, new AdaptiveRecvByteBufAllocator());
    }
  protected DefaultChannelConfig(Channel channel, RecvByteBufAllocator allocator) {
        // channel  --> NioServerSocketChannel
        //allocator  预测器
        setRecvByteBufAllocator(allocator, channel.metadata());
        this.channel = channel;
    }
}

可以看到上面的一连串的操作,都是赋值的操作,将传入的NioServerSocketChannel赋值给DefaultChannelConfigchannel属性,将serverSocketChannel.socket()赋值给DefaultServerSocketChannelConfigjavaSocket的属性。到此NioServerSocketChannel初始化就完成了,同时将刚才创建好的NioServerSocketChannelConfig对象赋值给当前类的config的属性。至此channelFactory.newChannel()方法就执行完成,我们继续返回到原来的代码继续查看剩下的代码,具体的代码如下:

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
		//初始化并注册
    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            //通过反射创建NioServerSocketChannel
            //channelFactory=new ReflectiveChannelFactory  ---> constructor=NioServerSocketChannel.class.getConstructor();
            //channel=NioServerSocketChannel
          	//将创建好NioServerSocketChannel类赋值给该类的channel属性,继续执行剩下的代码
            channel = channelFactory.newChannel();
          	//接下来执行下面的方法
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                channel.unsafe().closeForcibly();
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }
        //config().group()==bossGroup  ===> EventLoopGroup bossGroup=new NioEventLoopGroup(1);
        //register开启了事件轮询线程
        //config().group()  boosGroup
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }
        return regFuture;
    }
}

上面的channelFactory.newChannel();执行完将对应的对象返回到对应的属性channel中去,然后执行对应的init(channel);的方法,我们打开init(channel);方法,具体的代码如下:

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
	@Override
    void init(Channel channel) throws Exception {
        //channel=NioServerSocketChannel
        //options0  获取的是用户自己设置的tcp参数  ServerBootstrap.option(ChannelOption.SO_BACKLOG,128)
        final Map<ChannelOption<?>, Object> options = options0();
        synchronized (options) {
            //设置用户设置的tcp参数
            setChannelOptions(channel, options, logger);
        }
        //attrs0()  ServerBootstrap.attr()  获取用户设置的attr参数
        final Map<AttributeKey<?>, Object> attrs = attrs0();
        synchronized (attrs) {
            for (Entry<AttributeKey<?>, Object> e : attrs.entrySet()) {
                @SuppressWarnings("unchecked")
                AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }
        //channel=NioServerSocketChannel
        //获取AbstractChannel.pipeline();的pipeline(DefaultChannelPipeline)
        ChannelPipeline p = channel.pipeline();
      	//这儿获取的之前初始化的NioEvetLoopGroup
        final EventLoopGroup currentChildGroup = childGroup;
      	//自己传入进来的Channelhandler 默认继承或者间接继承ChanelHandler
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions;
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
      	//将传入的参数设置到当前的option属性中
        synchronized (childOptions) {
            currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));
        }
      	//将传入的参数设置到当前的attr属性中
        synchronized (childAttrs) {
            currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));
        }
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) throws Exception {
                //System.out.println(ch==channel);   true
                final ChannelPipeline pipeline = ch.pipeline();
                //System.out.println(pipeline==p);  true
                //config.handler()=自己创建的new ChannelInitializer<ServerSocketChannel>()
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }
                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        //System.out.println("执行了");
                        //bossGroup将客户端连接转交给workerGroup
                        pipeline.addLast(
                          new ServerBootstrapAcceptor(ch, currentChildGroup, 
                          currentChildHandler, currentChildOptions,currentChildAttrs));
                    }
                });
            }
        });
    }
}

将之前的设置好的options,attrs设置到传入的NioServerSocketChannel 将对应的参数进行对应的赋值,然后执行addLast()的方法,具体的代码如下:

public class DefaultChannelPipeline implements ChannelPipeline {
  @Override
  public final ChannelPipeline addLast(ChannelHandler... handlers) {
    //handlers=new ChannelInitializer<Channel>
    return addLast(null, handlers);
  }
  @Override
  public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
    if (handlers == null) {
      throw new NullPointerException("handlers");
    }
    for (ChannelHandler h: handlers) {
      if (h == null) {
        break;
      }
      //executor = null
      //name = null
      //h = new ChannelInitializer<Channel>
      addLast(executor, null, h);
    }
    return this;
  }
  @Override
  public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
    //group=null
    //name =null
    //handler=new ChannelInitializer<Channel>
    final AbstractChannelHandlerContext newCtx;
    synchronized (this) {
      //检查添加
      checkMultiplicity(handler);
      //filterName(name, handler)   当我们没有指定名字时  给我们默认生成一个
      //new DefaultChannelHandlerContext()
      newCtx = newContext(group, filterName(name, handler), handler);
      addLast0(newCtx);
      if (!registered) {
        //判断handlerState属性等于0  并且设置为1
        newCtx.setAddPending();
        callHandlerCallbackLater(newCtx, true);
        return this;
      }
      //返回NioEvenGroup
      EventExecutor executor = newCtx.executor();
      if (!executor.inEventLoop()) {
        callHandlerAddedInEventLoop(newCtx, executor);
        return this;
      }
    }
    callHandlerAdded0(newCtx);
    return this;
  }
  
  private static void checkMultiplicity(ChannelHandler handler) {
        if (handler instanceof ChannelHandlerAdapter) {
            ChannelHandlerAdapter h = (ChannelHandlerAdapter) handler;
            //没有加这个注解同时又是单例的对象,下面直接会抛异常
            if (!h.isSharable() && h.added) {
                throw new ChannelPipelineException(
                        h.getClass().getName() +
                        " is not a @Sharable handler, so can't be added or removed multiple times.");
            }
            h.added = true;
        }
    }
}

上面的函数进行一连串的链式调用,最终调用到对应的方法,走来是执行checkMultiplicity()这儿,当添加的对象没有加对应的@ChannelHandler.Sharable注解,同时又是一个单例对象,这个时候就表示重复添加了。会直接报错。然后会调用对应的newContext(EventExecutorGroup group, String name, ChannelHandler handler)方法,具体的代码如下:

public class DefaultChannelPipeline implements ChannelPipeline {
  private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, 
                                                   ChannelHandler handler) {
        //group=null
        //name =没传系统默认创建
        //handler=new ChannelInitializer<Channel>
        return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler);
    }
}

上面的代码创建了一个DefaultChannelHandlerContext对象,我们继续跟进去,看创建的对象是什么样的,具体的代码如下:

final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
  DefaultChannelHandlerContext(
              DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
          //pipeline=DefaultChannelPipeline
          //executor=null
          //name =没传系统默认创建
          //handler=new ChannelInitializer<Channel>
          super(pipeline, executor, name, handler.getClass());
          //此Handler是ChannelInitializer
          this.handler = handler;
      }
}

当我们打开对应的代码发现,和之前创建头尾的节点是一致的。这个时候,我们就理解了。我们继续回到我们之前调用的代码的处,具体的代码如下:

public class DefaultChannelPipeline implements ChannelPipeline {
	@Override
  public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
    //group=null
    //name =null
    //handler=new ChannelInitializer<Channel>
    final AbstractChannelHandlerContext newCtx;
    synchronized (this) {
      //检查添加
      checkMultiplicity(handler);
      //filterName(name, handler)   当我们没有指定名字时  给我们默认生成一个
      //new DefaultChannelHandlerContext()
      newCtx = newContext(group, filterName(name, handler), handler);
      //执行如下对应的代码。
      addLast0(newCtx);
      if (!registered) {
        //判断handlerState属性等于0  并且设置为1
        newCtx.setAddPending();
        callHandlerCallbackLater(newCtx, true);
        return this;
      }
      //返回NioEvenGroup
      EventExecutor executor = newCtx.executor();
      if (!executor.inEventLoop()) {
        callHandlerAddedInEventLoop(newCtx, executor);
        return this;
      }
    }
    callHandlerAdded0(newCtx);
    return this;
  }
}

我们发现执行完了创建newContext方法过后,将创建好的DefaultChannelHandlerContext对象赋值给newCtx属性,然后调用addLast0(newCtx);方法,具体的代码如下:

public class DefaultChannelPipeline implements ChannelPipeline {
  private void addLast0(AbstractChannelHandlerContext newCtx) {
          //newCtx=new DefaultChannelHandlerContext()
          AbstractChannelHandlerContext prev = tail.prev;
          newCtx.prev = prev;
          newCtx.next = tail;
          prev.next = newCtx;
          tail.prev = newCtx;
      }
}

我们发现将我们创建好的DefaultChannelHandlerContext对象添加对应的队列中去。这个时候构建出来的是我们前面创建好的匿名内部类ChannelInitializer至此addLast0()执行完成,这个时候,返回到原来的方法。具体如下:

public class DefaultChannelPipeline implements ChannelPipeline {
	@Override
  public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
    //group=null
    //name =null
    //handler=new ChannelInitializer<Channel>
    final AbstractChannelHandlerContext newCtx;
    synchronized (this) {
      //检查添加
      checkMultiplicity(handler);
      //filterName(name, handler)   当我们没有指定名字时  给我们默认生成一个
      //new DefaultChannelHandlerContext()
      newCtx = newContext(group, filterName(name, handler), handler);
      addLast0(newCtx);
      //默认registered是false,这个if是
      if (!registered) {
        //判断handlerState属性等于0  并且设置为1
        newCtx.setAddPending();
        callHandlerCallbackLater(newCtx, true);
        return this;
      }
      //返回NioEvenGroup
      EventExecutor executor = newCtx.executor();
      if (!executor.inEventLoop()) {
        callHandlerAddedInEventLoop(newCtx, executor);
        return this;
      }
    }
    callHandlerAdded0(newCtx);
    return this;
    }
}

上面的if判断是直接可以进的,因为registered的没有改变过,默认是false,所以这个if判断是可以进入的,然后执行if判断中两个方法,具体的代码如下:

abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
	final void setAddPending() {
   	 		//通过CAS操作将HANDLER_STATE_UPDATER从INIT改成ADD_PENDING
    		//将状态改成添加待处理
        boolean updated = HANDLER_STATE_UPDATER.compareAndSet(this, INIT, ADD_PENDING);
        assert updated; 
    }
}

上面的代码主要改的是传进来的对象的状态从INIT改成ADD_PENDING,接下来,我们继续查看 callHandlerCallbackLater(newCtx, true);方法的代码,具体的代码如下:

public class DefaultChannelPipeline implements ChannelPipeline {
	private void callHandlerCallbackLater(AbstractChannelHandlerContext ctx, boolean added) {
        assert !registered;
    		//传入进来added等于true,所以执行的new PendingHandlerAddedTask(ctx)
        PendingHandlerCallback task = added ? new PendingHandlerAddedTask(ctx) : new PendingHandlerRemovedTask(ctx);
        PendingHandlerCallback pending = pendingHandlerCallbackHead;
        if (pending == null) {
            pendingHandlerCallbackHead = task;
        } else {
            // Find the tail of the linked-list.
            while (pending.next != null) {
                pending = pending.next;
            }
            pending.next = task;
        }
    }
}

上面传进来的addedtrue,所以执行的是new PendingHandlerAddedTask(ctx)我们继续跟进去看看,具体的代码如下:

private final class PendingHandlerAddedTask extends PendingHandlerCallback {
 PendingHandlerAddedTask(AbstractChannelHandlerContext ctx) {
   super(ctx);
 }
}
private abstract static class PendingHandlerCallback implements Runnable {
  final AbstractChannelHandlerContext ctx;
  PendingHandlerCallback next;
  PendingHandlerCallback(AbstractChannelHandlerContext ctx) {
    this.ctx = ctx;
  }
}

最终发现就是给对应属性ctx进行赋值。同时它还实现了Runnable接口,由于我们的pendingHandlerCallbackHead走来是空的,所以会将我们刚创建的PendingHandlerAddedTask(ctx)赋值给pendingHandlerCallbackHead,至此addLast方法执行完成。我们返回到原来调用addLast方法地方去,继续跟进我们的代码。

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
		//初始化并注册
    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            //通过反射创建NioServerSocketChannel
            //channelFactory=new ReflectiveChannelFactory  ---> constructor=NioServerSocketChannel.class.getConstructor();
            //channel=NioServerSocketChannel
          	//将创建好NioServerSocketChannel类赋值给该类的channel属性,继续执行剩下的代码
            channel = channelFactory.newChannel();
          	//初始化channel完毕,继续执行下面的方法
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                channel.unsafe().closeForcibly();
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }
        //config().group()==bossGroup  ===> EventLoopGroup bossGroup=new NioEventLoopGroup(1);
        //register开启了事件轮询线程
        //config().group()  boosGroup
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }
        return regFuture;
    }
}

上面的init(channel);初始化完毕后,我们再来看看NioServerSocketChannel是什么样的,具体如下图:

在这里插入图片描述

至此初始化和赋值NioServerSocketChannel就此结束,我会在下一篇博客介绍注册方法config().group().register(channel);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值