NOTE

2.61 1.服务端的创建

bind 从这行代码开始,追踪bind 最终会来到io.netty.bootstrap.AbstractBootstrap#doBind - initAndRegister channel 要知道channelFactory是哪个,我们需要回到这行代码 - io.netty.bootstrap.Ab

Java创建于 更新于 historical

这是历史学习笔记,可能存在过时或不完整的理解。

bind

从这行代码开始,追踪bind

ChannelFuture future = bootstrap.bind(8000).sync();

最终会来到io.netty.bootstrap.AbstractBootstrap#doBind

private ChannelFuture doBind(final SocketAddress localAddress) {
        final ChannelFuture regFuture = initAndRegister();//这行
        final Channel channel = regFuture.channel();
        .....
}
  • initAndRegister
final ChannelFuture initAndRegister() {
    Channel channel = null;
	//..
		//调用channelFactory的newChannel创建,我们需要知道channelFactory是哪个?
        channel = channelFactory.newChannel();
        init(channel);

	//...

    return regFuture;
}

channel

要知道channelFactory是哪个,我们需要回到这行代码

ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup,workerGroup)
        .channel(NioServerSocketChannel.class)//关键
  • io.netty.bootstrap.AbstractBootstrap#channel
public B channel(Class<? extends C> channelClass) {
    if (channelClass == null) {
        throw new NullPointerException("channelClass");
    }
    //这个方法会将channelFactory赋值为ReflectiveChannelFactory
    return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}

如上,我们知道了channelFactory.newChannel()中的factory是ReflectiveChannelFactory,并且服务器启动时对应的channelClass是NioServerSocketChannel.class。 首先看下他的newChannel方法

  • io.netty.channel.ReflectiveChannelFactory#newChannel
 public T newChannel() {
	try {
		//使用反射调用无参构造方法,即NioServerSocketChannel
		return clazz.getConstructor().newInstance();
	} catch (Throwable t) {
		throw new ChannelException("Unable to create Channel from class " + clazz, t);
	}
}

创建NioServerSocketChannel

  • 构造方法
public NioServerSocketChannel() {
	//newSocket是通过jdk底层的provider.openServerSocketChannel()
	//接着调用有参构造方法
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

 public NioServerSocketChannel(ServerSocketChannel channel) {
	//调用父类AbstractNioMessageChannel的构造
	//AbstractNioMessageChannel会接着调用父类AbstractNioChannel的构造
    super(null, channel, SelectionKey.OP_ACCEPT);
    //参数配置类,用于配置options等
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
  • AbstractNioChannel
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
	//调用AbstractChannel
	//客户端和服务器都是实现了他
    super(parent);
    this.ch = ch;
    this.readInterestOp = readInterestOp;
    try {
        ch.configureBlocking(false);//nio配置为非阻塞模式
    } 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

protected AbstractChannel(Channel parent) {
    this.parent = parent;
    id = newId();//channelId
    unsafe = newUnsafe();//unsafe类,用于与底层jdk nio api交互
    pipeline = newChannelPipeline();//创建pipeline
}