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創建完成,並且完成了其初始化。