您的位置:首页 > 其它

Netty源码分析(一):服务端启动

2019-06-30 12:45 169 查看

Netty服务端启动的四个过程
1.创建服务端Channel
2.初始化服务端Channel
3.注册到Selector
4.端口绑定

文章目录

创建服务端Channel

创建服务端Channel的步骤:

  • 通过bind方法追踪代码,如下:

    可以看到下面的代码:

    追踪进去可以看到:


    看看该方法是怎样创建管道的

  • 这个clazz是哪个类?
    在利用辅助类进行配置信息的时候,我们传入了一个类,这个类就是我们配置信息传入的那个类

    追踪一下:


    这就是clazz的赋值情况

  • 传入的NioSocketChannel是一个什么样的类?创建的细节是什么?

    先来看四个类的继承关系以及在创建过程中的作用(顶层为父类,往下为子类)
    AbstractChannel:(3).创建id,unsafe,pipline
              |
    AbstractNioChannel:(2).设置非阻塞:configureBlocking(false)
              |
    AbstractNioMessageChannel:
              |
    NioSocketChannel:(1).newSocket()方法调用JDK底层代码创建ServerSokcetChannel
    创建tcp配置类NioServerSocketChannelConfig

  • 现在来看看为什么反射创建了NioSocketChannel创建了Channel了呢
    先来看NioSocketChannel的构造函数做了什么

    该构造函数调用了其他构造函数,传参是newSocket()方法的返回,看看newSocket()方法

    这块代码就是调用JDK代码来创建Channel了,可以看到返回值是ServerSocketChannel,这个在NIO中比较熟悉了。
    看一下被调用的构造函数

    同时创建了TCP配置类NioServerSocketChannelConfig,这些就是括号(1)
    下面跟随super进入上上一级父类AbstractNioChannel

    可以看到NIO编程中的设置非阻塞模式,也就是括号(2)
    继续跟踪父类AbstractChannel

    这里创建了id,unsage,pipeline,也就是(3)

初始化服务端Channel


重点关注init()方法

  • 四个步骤:
    (1)set ChannelOptions,ChannelAttrs

    (2)set ChildOptions,set ChildAttrs(还是在init方法中)

    (3)配置pipeline

    拿到pipeline后将用户添加的handler添加到该pipeline上
    (4)在最后默认添加ServerBootstrapAcceptor(一个特殊的ChannelHandler)
  • ServerBootstrapAcceptor是一个新连接接入器,构造的参数都是配置信息中所传入的信息
    来看看这四个参数

    跟踪出处

    这是ServerBootstrap中的两个属性直接赋值过来的,而这两个属性就是在写代码时配置信息所配置的信息

    分别点入用户代码的这两个方法
    先点入group方法

    可以看到childGroup是传入的参数
    再跟踪childHandler

    childHandler也是传入的
    剩下的两个属性就是刚才初始化的两个属性

注册到selector上

同样是initAndRegister()方法

创建并且完成初始化后,就会调用register方法
register方法的结构图

所以注册到选择器需要重点关注register方法
这里留一个问题:
为什么追踪register方法追踪到的是EventLoopGroup,但是讲解这块展示的逻辑代码是AbstractChannel

  • 看下register方法

    追踪register0

    追踪doRegister方法,查看真正注册的方法内容

    下面看一下invokeHandlerAddedIfNeeded和fireChannelRegistered两个方法

    这两个方法分别对应于Handler中的两个继承方法,如下:

  • 最后看一下fireChannelActive方法,该方法不会被调用

    因为netty在这里只是进行了selector绑定的操作,并没有进行端口的绑定的操作。所以isActive方法会返回false

服务端口的绑定

方法结构图

  • 还是从doBind方法开始看,如下:

    追踪doBind0方法
    有一个问题:为什么追踪后是AbstractBootstrap的方法,但是讲解内容确是AbstarctChannel
    下面看一下AbstractChannel的bind方法

    doBind方法

    bind方法调用了JDK底层的bind方法,javaChannel返回开始通过JDK底层创建的Channel
    在这里真正完成了端口的绑定

  • 下面看一段逻辑

    这就调用了pipeline的fireChannelActive方法,也是一个传播事件,在初始化的时候当时没有调用这个fireChannelActive方法,所以在这里绑定完端口以后才调用。

关于后面为什么讲解又到了chnnelActive方法,而又调用了什么Autoread方法,这个不是很懂。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: