NioServerSocketChannel初始化流程分析

 一、NioServerSocketChannel对象创建

ServerBootstrap bind()方法开始:

进入doBind(localAddress)方法:


private ChannelFuture doBind(final SocketAddress localAddress) {  
    final ChannelFuture regFuture = initAndRegister();  
    final Channel channel = regFuture.channel();  
    ...  
}  

该方法很长,我们先只关注 initAndRegister() 这个方法调用:

final ChannelFuture initAndRegister() {  
    Channel channel = null;  
    try {  
        channel = channelFactory.newChannel();  
        ...  
      }  
}  

进入channelFactory.newChannel()方法后,我们发现它实际调用的是ReflectiveChannelFactorynewChannel( )方法,通过反射,来创建`Channel对象

@Override  
public T newChannel() {  
    try {  
        return clazz.newInstance();  
    } catch (Throwable t) {  
        throw new ChannelException("Unable to create Channel from class " + clazz, t);  
    }  
}  

而这clazz对象是怎么来的呢?看下面这段代码:(AbstractBootstrap)


public B channel(Class<? extends C> channelClass) {  
    if (channelClass == null) {  
        throw new NullPointerException("channelClass");  
    }  
  // 将NioServerSocket的class对象传入ReflectiveChannelFactory  
    return channelFactory(new ReflectiveChannelFactory<C>(channelClass));  
}  

这个就是我们在创建服务端代码: new ServerBootstrap().channel ( NioServerSocket.class) ,传入的class对象,到这里我们暂时了解到,服务端,ServerBootstrap通过反射的方式,
创建NioServerSocket的对象。

接下来,我们分析一下NioServerSocket的构造器里面,在创建channel时究竟做了哪些操作


// SelectorProvider SelectorProviderDEFAULT_SELECTOR_PROVIDER=SelectorProvider.provider() ,  

public NioServerSocketChannel() {  
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));  
}  

获取到java Nio的SelectorProvider对象,通过SelectorProvider 对象调用openServerSocketChannel创建ServerSocketChannel

private static ServerSocketChannel newSocket(SelectorProvider provider) {  
    try {  
        return provider.openServerSocketChannel();  
    } catch (IOException e) {  
        throw new ChannelException( "Failed to open a server socket.", e);  
    }  
}  

再回过头看NioServerSocketChannel()构造器,跟入this(newSocket(DEFAULT_SELECTOR_PROVIDER))

public NioServerSocketChannel(ServerSocketChannel channel) {  
    super(null, channel, SelectionKey.OP_ACCEPT);  
    // NioServerSocketChannelConfig对象用于配置Channel相关的TCP等参数,后面Channel初始化的时候用得到  
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());  
}  

继续跟进父类AbstractNioChannel构造器

protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {  
    super(parent);  
    this.ch = ch;  
    this.readInterestOp = readInterestOp;  
    try {  
        ch.configureBlocking(false);  //这个非常关键,设置Channel为非阻塞模式  
    } 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);  
    }  
}  

进入父类AbstractChannel构造器,这里将创建几个对Channel很重要的对象:
id: channel的id
unsafe :Channel中实际用于IO操作的类
pipeline: 管道,里面存放了各种Handler

protected AbstractChannel(Channel parent) {  
    this.parent = parent;  
    id = newId();  
    unsafe = newUnsafe();  
    pipeline = newChannelPipeline();  
}  

 二、NioServerSocketChannel初始化

 void init(Channel channel) throws Exception {
        // options0()获取的是父类AbstractBootstrap的option()方法传入的参数
        final Map<ChannelOption<?>, Object> options = options0();
        synchronized (options) {
        //channel.config()获取的就是上面提到的,创建NioServerSocketChannel初始化时创建的NioSocketChannelConfig对象,用于channel的一些TCP等设置
            channel.config().setOptions(options); 
        }
       //为NioServerSocketChannel设置相关属性
        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());
            }
        }

        ChannelPipeline p = channel.pipeline();

        final EventLoopGroup currentChildGroup = childGroup;
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions;
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
        synchronized (childOptions) {
            currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
        }
        synchronized (childAttrs) {
            currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
        }

        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(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(
                                currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    }

SanPiBrother
24 声望3 粉丝

菜鸡的救赎之路