Netty服務端Channel的創建與初始化


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM