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()
方法后,我们发现它实际调用的是ReflectiveChannelFactory
的newChannel( )
方法,通过反射,来创建`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));
}
});
}
});
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。