文档章节

小白带你认识netty(二)之netty服务端启动(上)

天空小小
 天空小小
发布于 2018/11/18 00:26
字数 1484
阅读 1.7K
收藏 1

上一章 中的标准netty启动代码中,ServerBootstrap到底是如何启动的呢?这一章我们来瞅下。

server.group(bossGroup, workGroup);
			server.channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100);
			server.childHandler(new DealNettyServerInitializer());
			

			ChannelFuture future = server.bind(7878).sync();

启动代码无非这么几行,我一行一行的瞅。

server.group(bossGroup, workGroup);

还记得上一章定义的两个NioEventLoopGroup不?bossGroup和workGroup。这里的ServerBootstrap的group方法就是将workGroup直接赋值给了该对象的childGroup。而bossGroup传到了其父类AbstractBootstrap中,进行保存。

看到这,我们知道了两个类的关系:ServerBootstrap是AbstractBootstrap的子类。

server.channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100);

会将NioServerSocketChannel的class对象作为参数构建ReflectiveChannelFactory对象。这是什么对象呢?进去看一下:

哦,原来是一个通过反射构建对象的工厂类。回到上一步,netty会把ReflectiveChannelFactory对象作为参数调用channelFactory()方法。进入这个方法看一下:

原来只是保存ReflectiveChannelFactory对象。注意,channel方法是属于AbstractBootstrap对象的,因此,ReflectiveChannelFactory对象是保存在AbstractBootstrap对象中的。

同样,option方法也是AbstractBootstrap对象的,options会保存该option对象,那这么说,options应该是一个集合了,

果然是一个map集合。

server.childHandler(new DealNettyServerInitializer());

childHandler是属于ServerBootstrap类的,所以将DealNettyServerInitializer对象赋值给了ServerBootstrap的childHandler成员变量。

至此,只是保存变量,没有使用。看下server.bind(7878)方法,此方法就是服务器启动的真正入口。

很简单,继续跟进,

调用doBind方法,继续跟进:

这么多代码,主要是initAndRegister方法,因此跟进去。

下面正式进入启动流程,启动流程大体分为4步:

1、创建服务端channel:NioServerSocketChannel

2、初始化服务端Channel:NioServerSocketChannel

3、注册Selector:将Channel注册到Selector上

4、端口的绑定:服务端端口的监听。

下面,一步一步的分析:

1、创建服务端channel:NioServerSocketChannel

忘了说了,这个bind方法是调用的AbstractBootstrap的方法哦,因此这个channelFactory就是channel()方法的参数ReflectiveChannelFactory,下图为证:

还记的ReflectiveChannelFactory的newChannel方法吗?

很明显,就是通过反射构建NioServerSocketChannel。因为我们传入的是NioServerSocketChannel的Class对象。

NioServerSocketChannel对象是生成了,我们一起看一下这个NioServerSocketChannel的构造方法吧。

这个newSocket是做了什么?

哦,原来是调用jdk的代码,生成Nio的ServerSocketChannel呀。继续查看:

跟进this:

记住,这里的第三个参数是accept事件,,后续我们还会提到。跟进父类的构造方法:

我们可以看到,NioServerSocketChannel的父类是AbstractNioMessageChannel。然后这个构造方法只是继续调用父类的构造方法。

我们又知道了,AbstractNioMessageChannel的父类是AbstractNioChannel。并且刚才说注意的accept事件,赋值给了AbstractNioChannel的成员变量readInterestOp,后续还会遇到。

注意这个方法,ch是什么?就是传进来的jdk原生的ServerSocketChannel,一次该方法明显是将此通道将被置于非阻塞模式。

继续跟进父类的构造方法:

我们又知道了AbstractNioChannel的父类是AbstractChannel。并且,在该构造方法中,实例化了id,unsafe和pipeline。

明显此处的NioMessageUnsafe的父类是AbstracNioUnsafe。

到这里,一系列的父类构造方法的调用结束了。我们先总结下他们之间的关系。

NioServerSocketChannel的父类是AbstractNioMessageChannel;AbstractNioMessageChannel的父类是AbstractNioChannel;AbstractNioChannel的父类是AbstractChannel;还有一个额外的关系

NioMessageUnsafe的父类是AbstractNioUnsafe。

即:

NioServerSocketChannel -> AbstractNioMessageChannel -> AbstractNioChannel -> AbstractChannel;

NioMessageUnsafe -> AbstractNioUnsafe

为啥非要强调这种继承关系?因为后续的调用很复杂,如果不记住他们的关系,很容易分不清楚变量是从何 而来的。。

好了,我再回到开始的NioServerSocketChannel的构造方法上:

看过了super一系列的调用,我们瞅下下面的代码。先看下javaChannel()干了什么?

调用了父类的javaChannel方法。NioServerSocketChannel的父类是AbstractNioMessageChannel,因此看AbstractMessageNioChannel类的javaChannel方法,我们发现AbstractMessageNioChannel类中并没有javaChannel方法,因此应该调用的是AbstractNioMessageChannel的父类AbstractNioChannel的javaChannel,我们看一下:

这个ch,不就是之前传入的jdk原声的ServerSocketChannel对象么。。。图下证:

因此javaChannel方法,获取的是原生的ServerSocketChannel对象。点个赞,这个方法的名字真是见名知意呀。那javaChannel().socket()我们就很容易知道了,就是打开一个socket连接。并将该连接封装到NioServerSocketChannelConfig对象中保存在NioServerSocketChannel的config成员变量上。至此,创建服务端channel:NioServerSocketChannel完成。

 

2、初始化服务端Channel:NioServerSocketChannel

回到initAndRegister方法,看完了NioServerSocketChannel的实例化,我们看下紧接着的代码init():

进入init方法:

哎呦,这个又一坨代码。。。。没关系,很多代码都很简单:

上面代码很简单,就是setChannelOptions和setChannelAttrs。

同理,setChildOptions和setChildAttrs。

首先声明下,initChannel方法不是立即被调用的哦,后面会讲到何时被调用。总之会被调用,但不是这里。

p是啥,,这个p就是NioServerSocketChannel里成员变量,准确的说是父类父类父类的成员变量,即AbstractChannel的成员变量。下图证:

那个initChannel的方法里的pipeline变量也是p。那pipeline是啥呢?以后会讲的,这里只要知道它是一个双向链表结构就可以了。

因此这段的意思是将handler对象放入到pipeline中。

看到这里,一下懵了,NioServerSocketChannel里面啥时候实例化的EventLoop对象呀?说明下,此刻还没有实例化,因为没有调用该方法,所以暂时不会又null异常。

这段的逻辑就是向pipeline中添加连接器ServerBootstrapAcceptor。

好了,今天先到这,下面两步代码太深,明天再继续吧。最后,一定要记住继承的关系。

 

© 著作权归作者所有

天空小小
粉丝 6
博文 29
码字总数 39213
作品 0
南京
程序员
私信 提问
加载中

评论(0)

小白带你认识netty(二)之netty服务端启动(下)

承接上一篇小白带你认识netty(二)之netty服务端启动(上),还剩下两步骤:3、注册Selector:将Channel注册到Selector上 和 4、端口的绑定:服务端端口的监听。 3、注册Selector:将Chann...

天空小小
2018/11/18
208
0
Netty在Android开发中的应用实战系列(一)——— 搭建服务端与客户端

阅读本文建议从第一篇开始往后看 本系列文章 Netty在Android开发中的应用实战系列(一)——— 搭建服务端与客户端 Netty在Android开发中的应用实战系列(二)——— Encoder | Decoder | Ha...

Code-Porter
2019/09/14
0
0
Kotlin + Netty 在 Android 上实现 Socket 的服务端

一. 背景 最近的一个项目:需要使用 Android App 作为 Socket 的服务端,并且一个端口能够同时监听 TCP/Web Socket 协议。 自然而然,项目决定采用 Netty 框架。Netty 服务端在收到客户端发来...

Tony沈哲
2019/08/11
0
0
RPC基本原理以及如何用Netty来实现RPC

前言 在微服务大行其道的今天,分布式系统越来越重要,实现服务化首先就要考虑服务之间的通信问题。这里面涉及序列化、反序列化、寻址、连接等等问题。。不过,有了RPC框架,我们就无需苦恼。...

清幽之地
2018/12/06
0
0
Netty + ZooKeeper 实现简单的服务注册与发现

一. 背景 最近的一个项目:我们的系统接收到上游系统的派单任务后,会推送到指定的门店的相关设备,并进行相应的业务处理。 二. Netty 的使用 在接收到派单任务之后,通过 Netty 推送到指定门...

Tony沈哲
2019/06/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

WebStorm mac:JavaScript多功能集成开发环境 2020.1

WebStorm mac是一款JavaScript 开发工具。WebStorm 为JavaScript和TypeScript带来了新的智能意图,改进了对Angular的支持,更新了CSS和HTML文档,更强大的调试控制台等等! 新增功能 新的默认...

麦克虾仔
26分钟前
14
0
什么是ESAM安全模块

ESAM(Embedded Secure Access Module)即嵌入式安全控制模块。ESAM硬件具有传感器(电压,时钟,温度,光照、过滤器(防止尖峰/毛刺)、独立的内部时钟(独立CLK) 、(SFI)的检测机制、...

Music121
34分钟前
17
0
跳表

数据结构,跳表。跳表是redis的一个核心组件,也同时被广泛地运用到了各种缓存地实现当中,它的主要优点,就是可以跟红黑树、AVL等平衡树一样,做到比较稳定地插入、查询与删除。理论插入查询...

A_laoshiren
34分钟前
13
0
【3D】姿态检测网络PoseCNN复现过程记录

最近在研究室内6D姿态检测相关问题,计划在PoseCNN网络基础上进行改进实现。但是在第一步的复现过程中踩了无数的坑,最终成功运行了demo,但目前数据集train还是遇到了一些问题。有问题欢迎一...

osc_gccs85s0
35分钟前
24
0
无监督学习算法

本文首发自公众号:RAIS,点击直接关注。 前言 本系列文章为 《Deep Learning》 读书笔记,可以参看原书一起阅读,效果更佳。 无监督学习算法 就是无监督的一种学习方法,太抽象,有一种定义...

我是任玉琢
36分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部