netty源码阅读之服务器启动之服务端channel的创建

首先是我们一段用户的代码 

    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue")
                    .handler(new ServerHandler())
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new AuthHandler());
                            //..

                        }
                    });

            ChannelFuture f = b.bind(8888).sync();

            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

我们分以下步骤分析源码:

1、通过什么方式创建服务端channel。

2、 创建服务端channel的时候做了什么事情。

通过什么方式创建服务端channel

从bind方法进入:层层深入,到了doBind方法,里面有一个initAndRegister()方法(在AbstractBootstrap类里面):

    final ChannelFuture initAndRegister() {
        Channel channel = null;

        try {
            channel = this.channelFactory.newChannel();
            this.init(channel);
        } catch (Throwable var3) {
            if(channel != null) {
                channel.unsafe().closeForcibly();
            }

            return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3);
        }

        ...
    }

也就是有一个channelFactory类工厂,产生我们的Channel。具体这个channelFactory的实现是什么?我们目前先猜测是ReflectiveChannelFactory,进入ReflectiveChannelFactory的newChannel()方法,明显是使用反射的实现:

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

那么这个clazz是什么?带着这两个疑问,来到用户代码的这一行:

 .channel(NioServerSocketChannel.class)

这一行好像和clazz有关。进入bind方法:

    public B channel(Class<? extends C> channelClass) {
        if(channelClass == null) {
            throw new NullPointerException("channelClass");
        } else {
            return this.channelFactory((io.netty.channel.ChannelFactory)(new ReflectiveChannelFactory(channelClass)));
        }
    }

看channelFactory方法,一直点进去,就是把传入的ReflectiveChannelFactory传递给AbstractBootstrap类,作为他的其中一个成员变量,这里就解释了前面的channelFactory的实现是什么,就是ReflectiveChannelFactory。

那么我们进入new ReflectiveChannelFactory(channelClass)看看它做了什么:

    public ReflectiveChannelFactory(Class<? extends T> clazz) {
        if(clazz == null) {
            throw new NullPointerException("clazz");
        } else {
            this.clazz = clazz;
        }
    }

很明显,刚刚的clazz就是我们用户传进去的NioServerSocketChannel.class

这里,创建服务端channel也就是NioServerSocketChannel的代码已经清晰了

创建服务端channel的时候做了什么事情

我们点进去NioServerSocketChannel这个类,看它的构造方法,也就是在构造的时候做了什么事情:

无参构造器:

    public NioServerSocketChannel() {
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }
DEFAULT_SELECTOR_PROVIDER的来源:
 private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
newSocket的来源:
    private static java.nio.channels.ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            return provider.openServerSocketChannel();
        } catch (IOException var2) {
            throw new ChannelException("Failed to open a server socket.", var2);
        }
    }

这些其实都是使用jdk底层构造ServerSocketChannel的方法创建的。

接下去看无参构造器调用一个参数的构造器:

    public NioServerSocketChannel(java.nio.channels.ServerSocketChannel channel) {
        super((Channel)null, channel, 16);
        this.config = new NioServerSocketChannel.NioServerSocketChannelConfig(this, this.javaChannel().socket());
    }

这里主要做了两件事情:

1、调用父类的构造器

2、初始化一个NioServerSocketChannelConfig,以后可以使用这个tcp参数设置类。

第二点可以不用解释了,第一点层层进入,到了AbstractNioChannel(这个AbstractNioChannel是服务端和客户端channel的基类,一些公共的东西都在这个类里面创建)的这个构造方法:

    protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        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);
        }
    }

首先把ch传入,然后把readInterestOp也传入,然后是一个nio编程很常用的设置,设置为非阻塞模式:

ch.configureBlocking(false);

最后我们查看第一行super(parent);

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

也就是为这个服务端channel添加一个id,一个unsafe、一个pipeline。

自此,我们创建服务端channel的源码已经分析完,记住这些东西,以后会串起来。

猜你喜欢

转载自blog.csdn.net/fst438060684/article/details/81427946