文档章节

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

天空小小
 天空小小
发布于 11/18 00:26
字数 1484
阅读 13
收藏 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。

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

 

© 著作权归作者所有

共有 人打赏支持
天空小小
粉丝 3
博文 29
码字总数 39213
作品 0
南京
程序员
私信 提问
小白带你认识netty(二)之netty服务端启动(下)

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

天空小小
11/18
0
0
Netty入门-client/server

一、环境准备 开发工具eclipse/idea(本人目前正在切换为idea),maven插件 最新版的netty包maven依赖 <dependency> 二、简单的client/server demo 功能:client端发送一个“query time orde...

dkz
2015/12/09
232
0
Netty干货分享:京东京麦的生产级TCP网关技术实践总结

1、引言 京东的京麦商家后台2014年构建网关,从HTTP网关发展到TCP网关。在2016年重构完成基于Netty4.x+Protobuf3.x实现对接PC和App上下行通信的高可用、高性能、高稳定的TCP长连接网关。 早期...

JackJiang2011
2017/12/01
0
0
从零开始学netty——开启客户端

[从零开始学netty——第一个netty程序][1] [从零开始学netty——认识decoder][2] 通过上面两篇文章,大家基本了解了一个netty的样子,为了专注介绍,特意省去了客户端的编写,使用telnet来当...

xpbob
05/02
0
0
Netty源码:从一个简单Demo开始

最近在看闪电侠的《Netty深入剖析》,记录总结。 一.Netty简单示例 首先先看一个简单的HelloWord:Server.java 和 ServerHandler.java Server.java 启动Server,运行结果如下: 二.Netty是对...

Jacktanger
07/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

mac 下 mysql 8.0.13 安装并记录遇到的问题 以便以后查看

安装 官网mysql 下载地址 安装过程 省去 安装好之后 下载navicat 错误1 链接 遇到 mysql 2003 - Can't connect to MySQL server 错误, 解决方案 重启mysql 服务 #错误2 ERROR 1045: Acces...

杭州-IT攻城狮
26分钟前
3
0

中国龙-扬科
29分钟前
1
0
[Spring4.x]基于spring4.x纯注解的Web工程搭建

在前文中已经说明了如何基于 Spring4.x+ 版本开发纯注解的非web项目,链接如下: https://my.oschina.net/morpheusWB/blog/2985600 本文则主要说明,如何在Web项目中,"基于spring纯注解方式...

morpheusWB
58分钟前
13
0
基础编程题目集-7-13 日K蜡烛图

股票价格涨跌趋势,常用蜡烛图技术中的K线图来表示,分为按日的日K线、按周的周K线、按月的月K线等。以日K线为例,每天股票价格从开盘到收盘走完一天,对应一根蜡烛小图,要表示四个价格:开...

niithub
今天
5
0
Jenkins window 下的安装使用

1.下载:https://jenkins.io/download/ 双击安装完毕,将自动打开浏览器: http://localhost:8080 打开对应位置的文件,将初始密钥粘贴至输入框。 第一个是 安装默认的软件;第二个是 自定义...

狼王黄师傅
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部