Netty创建服务端Channel时,从服务端 ServerBootstrap 类的 bind 方法进入,下图是创建服务端Channel的函数调用链。在后续代码中通过反射的方式创建服务端Channel,反射操作在创建服务端 Channel 对象的工厂的 newChannel 方法,创建服务端 Channel 对象的工厂在ServerBootstrap 类的 channel 方法中确定。

final ChannelFuture initAndRegister() { Channel channel = null; try { // 反射创建服务端Channel channel = channelFactory.newChannel(); init(channel); } ChannelFuture regFuture = config().group().register(channel); return regFuture; }
反射创建服务端Channel的工厂:
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> { private final Class<? extends T> clazz; public ReflectiveChannelFactory(Class<? extends T> clazz) { this.clazz = clazz; } @Override public T newChannel() { return clazz.getConstructor().newInstance(); } }
在服务端创建Channel的过程中,上述代码中传入的Class类为 NioServerSocketChannel.class,这个类是在配置ServerBootstrap时通过其channel()方法确定的,所以创建的服务端Channel对象也就是 NioServerSocketChannel 类的对象,实例化 NioServerSocketChannel 类时会调用该类及其父类的一系列 构造方法,这一过程中将会创建 jdk 底层的 jdk channel 以及做一些基础的初始化工作,比如设置服务端Channel的阻塞模式,创建服务端Channel的id、unsafe、pipeline成员等。

创建 NioServerSocketChannel 类对象的具体流程:

public NioServerSocketChannel() { this(newSocket(DEFAULT_SELECTOR_PROVIDER)); } public NioServerSocketChannel(SelectorProvider provider) { this(newSocket(provider)); } public NioServerSocketChannel(ServerSocketChannel channel) { super(null, channel, SelectionKey.OP_ACCEPT); config = new NioServerSocketChannelConfig(this, javaChannel().socket()); } protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent, ch, readInterestOp); } protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent); this.ch = ch; this.readInterestOp = readInterestOp; ch.configureBlocking(false); } protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); unsafe = newUnsafe(); pipeline = newChannelPipeline(); }
由以上的构造方法可知,每一个Channel在创建的时候都会为其分配一个新的ChannelPipeline,这项关联是永久性的,Channel既不能附加另外一个ChannelPipeline,也不能分离其当前的。ChannelPipeline中以链式结构存储ChannelHandlerContext,在刚开始创建ChannelPipeline的时候会先创建两个节点:head、tail节点,后续再往ChannelPipeline中添加ChannelHandler时可调用ChannelPipeline的addLast方法进行添加,处理过程中会将ChannelHandler封装为ChannelHandlerContext,然后添加进去。
// 创建ChannelPipeline对象时会先创建head、tail节点
protected DefaultChannelPipeline(Channel channel) { this.channel = ObjectUtil.checkNotNull(channel, "channel"); succeededFuture = new SucceededChannelFuture(channel, null); voidPromise = new VoidChannelPromise(channel, true); tail = new TailContext(this); head = new HeadContext(this); head.next = tail; tail.prev = head; }
// 在ChannelPipeline中新添加一个ChannelHandler
private void addLast0(AbstractChannelHandlerContext newCtx) { AbstractChannelHandlerContext prev = tail.prev; newCtx.prev = prev; newCtx.next = tail; prev.next = newCtx; tail.prev = newCtx; }
服务端Channel创建完成后会对其进行初始化,初始化工作大概就是保存用户自定义的属性,然后配置服务端的pipeline,再通过保存的用户属性创建一个连接接入器,并将其添加到服务端的pipeline,连接接入器每次accept新的连接之后都会使用这些属性对新连接做一些配置,过程如下:

配置服务端的pipeline的过程如下:
ChannelPipeline p = channel.pipeline(); p.addLast(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); // handler()方法返回由 ServerBootstrap 类的handler 方法设置的handler ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } ch.eventLoop().execute(new Runnable() { @Override public void run() { // ServerBootstrapAcceptor这个配置在服务端Pipeline中的handler,会对新接入的客户端Channel做一些配置,比如配置客户端 的ChannelPipeline pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } });
// ServerBootstrapAcceptor配置客户端Channel的过程
public void channelRead(ChannelHandlerContext ctx, Object msg) { final Channel child = (Channel) msg; child.pipeline().addLast(childHandler); setChannelOptions(child, childOptions, logger); for (Entry<AttributeKey<?>, Object> e: childAttrs) { child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue()); } childGroup.register(child).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { forceClose(child, future.cause()); } } }); }
至此Netty服务端Channel创建完成,并且完成了其初始化。