Netty源码解读 - 服务端channel的创建和初始化:

本文深入探讨了Netty中服务端Channel的创建和初始化过程,从bind()开始,详细阐述了initAndRegister()、newChannel()以及init()步骤。分析了channelFactory().newChannel方法,揭示了NioServerSocketChannel的构造过程,包括创建底层channel、配置TCP参数等。同时,总结了服务端Channel初始化阶段的关键操作,如setChannelOptions、setChildOptions、配置pipeline和添加连接器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、服务端channel的创建和初始化流程
bind() 服务端绑定端口号
——> initAndRegister() 初始化并且注册
———— > newChannel() 创建服务端Channel
———— > init()初始化服务端channel

从bind进入:
    ChannelFuture sync = bootstrap.bind(port).sync();
      public ChannelFuture bind(int inetPort) {
        return bind(new InetSocketAddress(inetPort));
    }
  public ChannelFuture bind(SocketAddress localAddress) {
         validate();  //进行参数校验
         if (localAddress == null) {
             throw new NullPointerException("localAddress");
         }
         return doBind(localAddress); //重点-----------------------》详细解读
     }
     
 主要分析dobind()方法如下:
   1、初始化一个channel实例
   2、将配置信息和channel进行绑定
   3、调用NIO的bind操作来绑定端口
   private ChannelFuture doBind(final SocketAddress localAddress) {
           //通过initAndRegister进行初始化和注册,可以知道是需要拿到channel通道的实例
 
           final ChannelFuture regPromise = initAndRegister(); //----------》下面是详细解析
           final Channel channel = regPromise.channel();
           final ChannelPromise promise = channel.newPromise();
           if (regPromise.isDone()) {
           //端口绑定操作,最终是通过封装的NIO中的bind操作来完成端口的绑定
               doBind0(regPromise, channel, localAddress, promise);   // 这是NioEventLoop启动的关键方法
           } else {
               regPromise.addListener(new ChannelFutureListener() {
                   @Override
                   public void operationComplete(ChannelFuture future) throws Exception {
                       doBind0(future, channel, localAddress, promise);
                   }
               });
           }
           return promise;
       }
       
       initAndRegister()方法的部分代码:
       final ChannelFuture initAndRegister() {
      //通过分析channel实例是NIOServerSocketChannel类型的实例
        final Channel channel = channelFactory().newChannel();//----------------重点 创建channel
        try {
            init(channel); //----------------------------》重点   初始化线程
        } catch (Throwable t) {
            channel.unsafe().closeForcibly();
            return channel.newFailedFuture(t);
        }

2、创建服务端channel: -------》channelFactoyr().newChannel 方法的详细解析
源码追踪:initAndRegister()---->channelFactoyr().newChannel
这个channelFactory()的类型对应Serverbootstrap.channel()方法 ;
此处的channel()传入的是NioServerSocketChanne.class,,继续跟源码,会发现他通过ReflectiveChannelFactory会通过反射创建出一个NioServreSokcetChannel对象来。
此处主要分析NioServerSocketChannel的构造方法:源码已看
此构造方法主要干了一下几件事:
newSocket 创建底层channel
NioServerSocketChannelConfig() //配置tcp中的参数
AbstbstractNioChannel()
configureBlockconfigureBlocking(false) ,//设置阻塞模式
AbstractChannel() // 配置channel的标志idunsafe,还有pipeline

3、服务端channel的初始化 init方法的解析
(1) 、setChannelOptions、ChannelAttrs (配置可选操作项,对应serverBootStrap中的 .option() 和 .attr()中的值 )
(2)、setChildOptions、childAttrs(配置子线程的可选操作,对应serverBootStrap中的.chileOption() 和 childAttr() 的值 )
(3) 、配置服务端的pipeline (对应的ServerBootStrap中的 handler() )
(4)、添加连接器(其实就是将childChannel作为一个ChannelHandler添加进主事件的pipeline中)
源码如下:

 void init(Channel channel) throws Exception {
        
   //1、setChannelOptions 和setChannelAttrs 
           //获取主事件循环的相关options的配置
        final Map<ChannelOption<?>, Object> options = options();
        synchronized (options) {
        //通过同步操作将option配置信息配置到channel实例上
            channel.config().setOptions(options);
        }
          //通过同步操作将attr配置信息配置到channel实例上
        final Map<AttributeKey<?>, Object> attrs = attrs();
        synchronized (attrs) {
      
            for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
                @SuppressWarnings("unchecked")
                AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }
        //chennel实例的pipeline()的实例,添加的是channelHandler的实例,一般不配置
        ChannelPipeline p = channel.pipeline();
        if (handler() != null) {
            p.addLast(handler());
        }
        
    //2、 配置setChildOptions、childAttrs
        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()));
        }

   //3 、 往主事件循环中添加的channelhandler,
      p.addLast(new ChannelHandler[]{new ChannelInitializer<Channel>() {
            public void initChannel(final Channel ch) throws Exception {
                final ChannelPipeline pipeline = ch.pipeline();
                ChannelHandler handler = ServerBootstrap.this.config.handler();
                if (handler != null) {
                    pipeline.addLast(new ChannelHandler[]{handler});
                }
                
    //4、子事件循环组的group实例,options\handler等信息实例化了一个channelhandler
       //即子事件循环组作为主事件循环组的一个channelhandler来处理channel
                ch.eventLoop().execute(new Runnable() {
                    public void run() {
                        pipeline.addLast(new ChannelHandler[]{
                        new ServerBootstrap.ServerBootstrapAcceptor(ch, currentChildGroup, 
                        currentChildHandler, currentChildOptions, currentChildAttrs)});
                    }
                });
            }
        }});
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值