3-2-1 NioServerSocketChannel 的创建
Posted programmLover
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3-2-1 NioServerSocketChannel 的创建相关的知识,希望对你有一定的参考价值。
一 NioserverSocketChannel 创建时机:
NioServerSocketChannel 会在 AbstractBootstrap#bind(int) 绑定端口时调用到 AbstractBootstrap.initAndRegister() 方法创建 ChannelFuture,调用 ChannelFactory.newChannel(),通过反射来创建 NioServerSocketChannel 实例。
二 服务端 Channel 创建流程
1. 进入 NioServerSocketChannel 默认构造方法,查看 NioServerSocketChannel 创建流程
/**
* Create a new instance
*/
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
NioServerSocketChannel() 会先调用 NioServerSocketChannel#newSocket 创建一个 Nio 的 ServerSocketChannel 实例,然后继续调用重载的构造方法
继续跟进到 NioServerSocketChannel(ServerSocketChannel channel)
/**
* Create a new instance using the given {@link ServerSocketChannel}.
*/
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
NioServerSocketChannel(ServerSocketChannel channel) 调用父类的构造方法 AbstractNioMessageChannel#bstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp), 然后 创建一个 NioServerSocketChannelConfig 实例并保存
继续跟进 AbstractNioMessageChannel#bstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp)
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
又是父类的 构造方法,再跟进到 AbstractNioChannel#AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp)
/**
* Create a new instance
*
* @param parent the parent {@link Channel} by which this instance was created. May be {@code null}
* @param ch the underlying {@link SelectableChannel} on which it operates
* @param readInterestOp the ops to set to receive data from the {@link SelectableChannel}
*/
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
//保存 Nio 的 SocketChannel, readInterestOp
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
//配置为 非阻塞模式
ch.configureBlocking(false);
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
AbstractNioChannel#AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) 先继续调用父类构造方法 AbstractChannel#AbstractChannel(Channel parent),然后保存 Nio 的 SocketChannel, readInterestOp,从上一步方法我们得知,这里传入的 readInterestOp 应为SelectionKey.OP_READ,再配置为非阻塞模式
继续跟进到 AbstractChannel#AbstractChannel(Channel parent)
/**
* Creates a new instance.
*
* @param parent
* the parent of this channel. {@code null} if there\'s no parent.
*/
protected AbstractChannel(Channel parent) {
//设置parent
this.parent = parent;
//创建并设置 ChannelId、Unsafe、DefaultChannelPipeline
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
AbstractChannel#AbstractChannel(Channel parent) 先设置parent,这里传入的parent 为 null, 然后创建 id,unsafe ,pipeline 并保存,unsafe 会根据不同的 Channel 创建不同的 Unsafe,通常服务端会创建 NioServerSocketChannel,创建的 unsafe 类型为 NioMessageUnsafe,客户端会创建 NioSocketChannel, 创建的 unsafe 类型为 NioByteUnsafe, pipeline 类型为 DefaultChannelPipeline
进入 NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) 构造方法,查看 config 创建实例流程
private NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) { super(channel, javaSocket); }
调用父类方法,继续跟进
进入 DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) 构造方法
/** * Creates a new instance. */ public DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) { super(channel); this.javaSocket = ObjectUtil.checkNotNull(javaSocket, "javaSocket"); }
DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) 构造方法继续调用父类构造器传入 ServerSocketChannel,然后保存 jdk 的 ServerSocket
进入 DefaultChannelConfig(Channel channel)
public DefaultChannelConfig(Channel channel) { this(channel, new AdaptiveRecvByteBufAllocator()); }
DefaultChannelConfig(Channel channel) 会先创建一个 AdaptiveRecvByteBufAllocator 实例,然后继续调用构造方法
进入 DefaultChannelConfig(Channel channel, RecvByteBufAllocator allocator)
protected DefaultChannelConfig(Channel channel, RecvByteBufAllocator allocator) { setRecvByteBufAllocator(allocator, channel.metadata()); this.channel = channel; }
DefaultChannelConfig(Channel channel, RecvByteBufAllocator allocator) 保存 channel 和 RecvByteBufAllocator
至此 NioServerSocketChannel 创建完成
以上是关于3-2-1 NioServerSocketChannel 的创建的主要内容,如果未能解决你的问题,请参考以下文章
2021-08-26:长度为N的数组arr,一定可以组成N^2个数字对。例如arr = [3,1,2],数字对有(3,3) (3,1) (3,2) (1,3) (1,1) (1,2) (2,3) (2