netty4 ServerBootstrap.bind(port) debug
代码是netty4自带的例子
我们在bind的行前加个断电,下面是ServerBootstrap.bind(port)方法所经历的一些步骤。
在AbstractBootstrap.initAndRegister()中实例化一个Channel并进行初始化配置。
(可以参考《Netty4 initAndRegister 解析》)
配置项为在初始化Bootstrap时我们传入的handlers和一些设置。
下面进行channel的初始化(可以参考《Netty 源码分析之 一 揭开 Bootstrap 神秘的红盖头 (客户端)》)
注意箭头所示,这里的channelFactory是ReflectiveChannelFacotry.
这里就返回一个NioServerSocketChannel类型的channel.
下面的init(channel)对刚生成的channel进行一些初始化配置。
接着往下看:
注意下面注释内容。这里有两个添加handler的动作,后面一个时延时的,为了确保所有的handler都被放置在ServerBootstrapAccepter之前。这时候就已经初始化完channle中的eventloop对象了,可以使用eventloop来执行该channel的一些工作。
初始化完channel之后:反回到initAndRegister()先看一下eventloop注册到channel。
EventLoop注册Channel
说白了就是获取一个线程来处理这个注册事件。
那么这个EventExecutor到底是什么?我们获得了这个EventExecutor之后我们进入它的register(channel)方法看看:
这里注意到,eventloop注册channel实际上是channel注册eventoloop。最终将当前的eventloop传入到channel中作为channel的属性。
下面的eventLoop.inEvenLoop()判断该eventloop线程是否当前线程。这里关于eventloop的内容要以《Netty4 initAndRegister 解析》为主,下面的内容总结的一般。
然后下面的doregister0调用的是AbstractChannel在子类中的实现。比如当前是NioServerSocketChannel.doBind()同样也是在这个子类中实现的。
下面这快是对EventLoop接口的分析。
最后我们进入这个loop线程的执行线程:
先到此为止我们继续上面的逻辑:
以上都是initAndRegister()方法中的逻辑。
接着往下走:
DefaultChannelPipeline{(LoggingHandler#0 = io.netty.handler.logging.LoggingHandler), (ServerBootstrap$ServerBootstrapAcceptor#0 = io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor)}
继续主流程:
这里同时要留意eventloop的用法。
Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期,下面就来看看EventLoopGroup是怎样工作的。
最终还是到channel.bind(...)这个方法来绑定。
下面进入:final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
前面将eventloop注册到channel中之后,这里取出channel的eventloop。
AbstractChannelHandlerContext这个东西有专门博文。
一直循环到ctx.outbound为true的时候,获取这个ctx。
还记得那个上行下行的图吗,这就是那里的感念。
下面进入到EventExecutor executor = next.executor();方法:有上图可知当前的executor属性为null。
我们进入channel().eventloop().这个地方需要返回一个EventExecutor类型的对象。
我们先看channel方法:
pipeline=DefaultChannelPipeline{(LoggingHandler#0 = io.netty.handler.logging.LoggingHandler), (ServerBootstrap$ServerBootstrapAcceptor#0 = io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor)}
这里的(LoggingHandler#0 = io.netty.handler.logging.LoggingHandler)是什么鬼?
还记得上面的init(channel)吗,我们在那里添加了handler和ServerBootstrapAccepter。
下面我们还会涉及到这个handler。
先不管我们先进入pipeline.channel();方法
return channel().eventLoop();这里执行完channel()方法后我们进入eventloop()方法:
这里需要返回一个EventExecutor类型的对象。
然而这里返回的却是一个NioEventLoop类型的对象。我们在看一下关系图:
先不管我们接着看:下面进入父类的方法:
最终我们执行完了这个方法,返回一个EventLoop类型的对象。
NioEventLoop类型的对象怎么会是EventExecutor类型呢?
通过NioEventLoop类型检索我们发现
原来EventLoop继承了EventExecutor接口。没办法社区办idea功能比较简陋,就不画类型关系图了。
那么我们接着netty流程往下走:
在下面这个方法这里循环所有的handler的bind()方法。
这里的handler:LoggingHandler。还记得上面的疑问吗。答案在这里。
当前的handler是LoggingHandler那么我们就进入到:
这里又一个非常值得注意的地方。LoggingHandler的bind()方法并没有写什么业务逻辑,只打印了个日志:
18:33:33.694 [nioEventLoopGroup-2-1] INFO i.n.handler.logging.LoggingHandler - [id: 0x62c8b900] BIND: 0.0.0.0/0.0.0.0:8007
然后直接调用了下一个handler的bind()方法。
这个bind()方法是定义在ChannelOutboundHandler中的方法。
所有我们就行入到下一次循环中了:
开始循环了。
下一个handler:
到这里终于跳出netty框架到老nio层了!
但是到这的时候程序没进入bind直接跳出来了:
这里成功了?
我们专门打个断点到那个nio bind的地方。根据以上的流程分析我们知道最终的nio层bind就在我们非常熟悉的NioServerSocketChannel中实现。
我们手动进入这个类中找到bind方法:
这就和我们平时直接用nio写业务时一样了:
netty4 ServerBootstrap.bind(port) debug的更多相关文章
- bind(port)与.localAddress(new InetSocketAddress(port))区别
两者并没有什么区别,最后都会调用AbstractBootstrap这个抽象类的bind()方法.
- Netty4 ServerBootstrap 初始化channelFactory ReflectiveChannelFactory
只需要在启动之前传入你需要用的channel类型就可以了. ServerBootstrap初始化channelFactory过程: 最后我们再来看看这个channelFactory的使用场景:
- Netty4 initAndRegister 解析
我们从框架的应用层面来分析,NioEventLoopGroup在netty中的使用. 这是我们需要配置的地方. 紧接着我们进入netty的运行中.ServerBootstrap.bind(PORT); ...
- netty4.0 Server和Client的通信
netty4.0 Server和Client的通信 创建一个maven项目 添加Netty依赖 <dependency> <groupId>io.netty</group ...
- 【Netty源码学习】ServerBootStrap
上一篇博客[Netty源码学习]BootStrap中我们介绍了客户端使用的启动服务,接下来我们介绍一下服务端使用的启动服务. 总体来说ServerBootStrap有两个主要功能: (1)调用父类Ab ...
- 《精通并发与Netty》学习笔记(08 - netty4+springboot项目案例)
本节通过案例介绍springboot与netty的集成 第一步:新建Spring Initializr 项目 我这里选择Gradle项目,也可选择Maven项目 (注意:最好选择自己下载gradle, ...
- Netty学习笔记(二)——netty组件及其用法
1.Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 原生NIO存在的问题 1) NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector.Se ...
- 序列化在Netty中的使用
Java序列化的缺点 1.无法跨语言 对于Java序列化后的字节数组,别的语言无法进行反序列化 2.序列化后的码流过大 3.序列化性能低 使用JDK自带的序列化进行对象的传输 被传输的,实现了序列化接 ...
- Netty解决TCP粘包/拆包问题 - 按行分隔字符串解码器
服务端 package org.zln.netty.five.timer; import io.netty.bootstrap.ServerBootstrap; import io.netty.cha ...
随机推荐
- Linux添加用户并赋予/取消管理员权限
Ubuntu sudo adduser username # 添加用户 sudo adduser username sudo # 追加管理员权限 grep -Po '^sudo.+:\K.*$' /e ...
- docker run 的背后的故事(zz)
当利用docker run来创建并启动容器的时候,docker后台标准的操作包括: 1.检查本地是否存在指定的镜像,不存在就从公有仓库下载. 当我依瓢画葫芦的运行: sudo docker run - ...
- AC日记——[Ahoi2013]作业 bzoj 3236
3236 思路: 莫队+树状数组维护: 代码: #include <cmath> #include <cstdio> #include <cstring> #inc ...
- Eureka Server设计(转载 石杉的架构笔记)
目录: 一.问题起源 二.Eureka Server设计精妙的注册表存储结构 三.Eureka Server端优秀的多级缓存机制 四.总结 一.问题起源 Spring Cloud架构体系中,Eurek ...
- 【HNOI2008】玩具装箱
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具 ...
- 【状压基础题】poj3254 Corn Fields
题目大意 :农夫约翰有n*m块地,其中一些地荒掉了.玉米是一种傲娇的植物,种在相邻的地里会导致不孕不育.求所有种法数对100000000求余. 读入:第一行一个n一个m, 接下来是一个n行m列的矩形, ...
- 选择快速源来加速linux系统更新
sudo pacman-mirrors -c China -g 引用自manjaro百度贴吧
- 【计算几何】【极角序】【前缀和】bzoj1132 [POI2008]Tro
把点按纵坐标排序,依次枚举,把它作为原点,然后把之后的点极角排序,把叉积的公式稍微化简一下,处理个后缀和统计答案. #include<cstdio> #include<cmath&g ...
- python3开发进阶-Django框架的Form表单系统和基本操作
阅读目录 什么是Form组件 常用字段和插件 自定义校验的方式 补充进阶 一.什么是Form组件 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标 ...
- 1.3(java学习笔记)构造方法及重载
构造方法,用于对象的初始化,在创建对象时被自动调用的特殊方法.构造方法名称与类名一致,通过new调用. 下面通过代码来详细讲解 public class Point { int x, y; publi ...