跟闪电侠学 Netty:Netty 即时聊天实战与底层原理

跟闪电侠学 Netty:Netty 即时聊天实战与底层原理

作者:俞超
语言:中文
出版:电子工业出版社
ISBN:9787121426797
出版时间:2022-3
页数:344
定价:108
装帧:
购买纸质书

内容简介

内容已隐藏,请登录后查看

登录后继续查看

作者简介

闪电侠(俞超),某互联网公司技术专家。精通Netty、Spring、MyBatis 等开源框架。负责公司各类长连项目的开发与维护,有千万级别实时在线连接、百亿吞吐长连通信经验。Vim和IDEA党,对效率和编写优美代码有极致追求。

简书“Netty源码分析”专栏作者。

异常火爆的慕课“IntelliJ IDEA神器使用技巧”作者。

慕课“Netty源码分析视频教程”作者。

微信公众号:闪电侠的博客。

个人微信号:823797837。

欢迎读者联系笔者进行技术交流。

本书目录

上篇 入门实战
第1章 即时聊天系统简介2
1.1 单聊流程2
1.2 单聊的指令3
1.2.1 指令图示3
1.2.2 指令列表4
1.3 群聊流程4
1.4 群聊要实现的指令集5
1.4.1 指令图示5
1.4.2 指令列表6
1.5 Netty7
1.5.1 客户端使用Netty的程序逻辑结构7
1.5.2 服务端使用Netty的程序逻辑结构8
1.6 本书实现的即时聊天形式8
第2章 Netty是什么9
2.1 IO编程9
2.2 NIO编程12
2.2.1 线程资源受限12
2.2.2 线程切换效率低下13
2.2.3 IO读写面向流13
2.3 Netty编程16
第3章 Netty开发环境配置20
3.1 Maven20
3.1.1 下载20
3.1.2 配置和验证21
3.2 Git21
3.2.1 下载与安装21
3.2.2 配置22
3.3 IntelliJ IDEA22
第4章 服务端启动流程27
4.1 服务端启动最小化代码27
4.2 自动绑定递增端口28
4.3 服务端启动的其他方法30
4.3.1 handler()方法30
4.3.2 attr()方法30
4.3.3 childAttr()方法30
4.3.4 option()方法31
4.3.5 childOption()方法31
4.4 总结31
第5章 客户端启动流程32
5.1 客户端启动Demo32
5.2 失败重连34
5.3 客户端启动的其他方法35
5.3.1 attr()方法35
5.3.2 option()方法36
5.4 总结36
5.5 思考36
第6章 客户端与服务端双向通信37
6.1 客户端发送数据到服务端37
6.2 服务端读取客户端数据39
6.3 服务端返回数据到客户端40
6.4 总结42
6.5 思考42
第7章 数据载体ByteBuf的介绍43
7.1 ByteBuf的结构43
7.2 容量API44
7.3 读写指针相关的API45
7.4 读写API46
7.5 实战49
7.6 总结52
7.7 思考52
第8章 客户端与服务端通信协议编解码53
8.1 什么是客户端与服务端的通信协议53
8.2 通信协议的设计54
8.3 通信协议的实现56
8.3.1 Java对象56
8.3.2 序列化57
8.3.3 编码:封装成二进制数据的过程59
8.3.4 解码:解析Java对象的过程59
8.4 总结61
8.5 思考61
第9章 实现客户端登录62
9.1 登录流程62
9.2 逻辑处理器63
9.3 客户端发送登录请求64
9.3.1 客户端处理登录请求64
9.3.2 服务端处理登录请求64
9.4 服务端发送登录响应65
9.4.1 服务端处理登录响应65
9.4.2 客户端处理登录响应66
9.5 总结67
9.6 思考67
第10章 实现客户端与服务端收发消息68
10.1 收发消息对象68
10.2 判断客户端是否登录成功69
10.3 在控制台输入消息并发送71
10.4 服务端收发消息处理72
10.5 客户端收消息处理72
10.6 总结74
10.7 思考74
第11章 Pipeline与ChannelHandler75
11.1 Pipeline与ChannelHandler的构成76
11.2 ChannelHandler的分类76
11.3 ChannelInboundHandler的事件传播77
11.4 ChannelOutboundHandler的事件传播79
11.5 总结81
11.6 思考82
第12章 构建客户端与服务端的Pipeline83
12.1 ChannelInboundHandlerAdapter与ChannelOutboundHandlerAdapter83
12.2 ByteToMessageDecoder85
12.3 SimpleChannelInboundHandler85
12.4 MessageToByteEncoder87
12.5 构建客户端与服务端的Pipeline89
12.6 总结90
12.7 思考91
第13章 拆包/粘包理论与解决方案92
13.1 拆包/粘包例子92
13.2 为什么会有粘包、半包现象94
13.3 拆包的原理95
13.4 Netty自带的拆包器95
13.4.1 固定长度的拆包器FixedLengthFrameDecoder95
13.4.2 行拆包器LineBasedFrameDecoder95
13.4.3 分隔符拆包器DelimiterBasedFrameDecoder95
13.4.4 基于长度域的拆包器LengthFieldBasedFrameDecoder96
13.5 如何使用LengthFieldBasedFrameDecoder96
13.6 拒绝非本协议连接97
13.7 客户端和服务端的Pipeline结构99
13.8 总结99
13.9 思考99
第14章 ChannelHandler的生命周期100
14.1 ChannelHandler的生命周期详解100
14.2 ChannelHandler生命周期各回调方法的用法举例104
14.2.1 ChannelInitializer的实现原理104
14.2.2 handlerAdded()方法与handlerRemoved()方法106
14.2.3 channelActive()方法与channelInActive()方法106
14.2.4 channelRead()方法106
14.2.5 channelReadComplete()方法106
14.3 总结106
14.4 思考107
第15章 使用ChannelHandler的热插拔实现客户端身份校验108
15.1 身份检验108
15.2 移除校验逻辑110
15.3 身份校验演示111
15.3.1 有身份认证的演示112
15.3.2 无身份认证的演示113
15.4 总结114
15.5 思考114
第16章 客户端互聊的原理与实现115
16.1 最终效果115
16.2 一对一单聊的原理116
16.3 一对一单聊的实现117
16.3.1 用户登录状态与Channel的绑定117
16.3.2 服务端接收消息并转发的实现119
16.3.3 客户端接收消息的逻辑处理121
16.3.4 客户端控制台登录和发送消息121
16.4 总结122
16.5 思考123
第17章 群聊的发起与通知124
17.1 最终效果124
17.2 群聊的原理125
17.3 控制台程序重构127
17.3.1 创建控制台命令执行器127
17.3.2 管理控制台命令执行器127
17.4 创建群聊的实现129
17.4.1 客户端发送创建群聊请求129
17.4.2 服务端处理创建群聊请求129
17.4.3 客户端处理创建群聊响应131
17.5 总结132
17.6 思考132
第18章 群聊的成员管理133
18.1 最终效果133
18.2 群的加入135
18.2.1 在控制台添加群加入命令处理器135
18.2.2 服务端处理加群请求136
18.2.3 客户端处理加群响应137
18.3 群的退出137
18.4 获取群成员列表138
18.4.1 在控制台添加获取群成员列表命令处理器138
18.4.2 服务端处理获取群成员列表请求139
18.4.3 客户端处理获取群成员列表响应140
18.5 总结141
18.6 思考142
第19章 群聊消息的收发及Netty性能优化143
19.1 群聊消息的最终效果143
19.2 群聊消息的收发实现145
19.3 共享Handler146
19.4 压缩Handler——合并编解码器147
19.5 缩短事件传播路径149
19.5.1 压缩Handler——合并平行Handler149
19.5.2 更改事件传播源151
19.6 减少阻塞主线程的操作152
19.7 如何准确统计处理时长153
19.8 总结154
第20章 心跳与空闲检测156
20.1 网络问题156
20.2 服务端空闲检测158
20.3 客户端定时发心跳数据包159
20.4 服务端回复心跳与客户端空闲检测160
20.5 总结162
20.6 思考162
下篇 源码分析
第21章 服务端启动流程解析164
21.1 服务端启动示例164
21.2 服务端启动的核心步骤166
21.3 创建服务端Channel168
21.3.1 创建JDK底层Channel170
21.3.2 创建 Channel 配置类171
21.3.3 设置Channel类型为非阻塞171
21.3.4 创建Channel核心组件172
21.3.5 创建服务端Channel小结174
21.4 初始化服务端Channel174
21.4.1 设置服务端Channel的Option与Attr174
21.4.2 设置客户端Channel的Option与Attr175
21.4.3 配置服务端启动逻辑175
21.4.4 初始化服务端Channel小结176
21.5 注册服务端Channel176
21.5.1 调用JDK底层注册Selector177
21.5.2 回调handlerAdded事件178
21.5.3 传播channelRegistered事件178
21.5.4 其他逻辑178
21.5.5 注册服务端Channel小结179
21.6 绑定服务端端口180
21.6.1 调用JDK底层绑定端口181
21.6.2 传播channelActive事件182
21.6.3 注册ACCEPT事件182
21.6.4 绑定服务端端口小结183
21.7 总结184
第22章 Reactor线程模型解析185
22.1 NioEventLoopGroup的创建185
22.1.1 确定NioEventLoop的个数186
22.1.2 NioEventLoopGroup的创建总体框架187
22.1.3 创建ThreadPerTaskExecutor188
22.1.4 创建NioEventLoop190
22.1.5 创建线程选择器192
22.1.6 NioEventLoopGroup的创建小结194
22.2 NioEventLoop对应线程的创建和启动195
22.2.1 NioEventLoop的启动入口195
22.2.2 创建线程并启动195
22.3 NioEventLoop的执行流程198
22.3.1 NioEventLoop的执行总体框架198
22.3.2 执行一次事件轮询199
22.3.3 处理产生 IO 事件的 Channel205
22.3.4 添加任务213
22.3.5 任务的执行220
22.3.6 NioEventLoop 的执行流程小结225
22.4 总结225
第23章 客户端连接接入流程解析227
23.1 新连接接入的总体流程228
23.2 检测到有新连接228
23.3 注册Reactor线程229
23.3.1 创建NioSocketChannel230
23.3.2 设置并绑定NioSocketChannel233
23.3.3 注册 Reactor 线程小结240
23.4 总结240
第24章 编码原理解析241
24.1 粘包与拆包241
24.1.1 为什么要粘包241
24.1.2 为什么要拆包242
24.2 拆包的原理242
24.3 Netty中拆包的基类242
24.4 拆包抽象243
24.4.1 累加数据244
24.4.2 将累加的数据传递给业务进行拆包245
24.4.3 清理字节容器246
24.4.4 将业务数据包传递给业务解码器处理247
24.5 行拆包器248
24.5.1 找到换行符的位置248
24.5.2 非discarding模式的处理249
24.5.3 discarding模式的处理250
24.6 特定分隔符拆包251
24.7 LengthFieldBasedFrameDecoder 进阶用法251
24.7.1 基于长度的拆包251
24.7.2 基于长度的截断拆包252
24.7.3 基于偏移长度的拆包252
24.7.4 基于可调整长度的拆包253
24.7.5 基于偏移可调整长度的截断拆包253
24.7.6 基于偏移可调整变异长度的截断拆包254
24.8 LengthFieldBasedFrameDecoder源码剖析254
24.8.1 构造函数254
24.8.2 实现拆包抽象255
24.9 总结260
第25章 ChannelPipeline解析261
25.1 ChannelPipeline的初始化262
25.2 ChannelPipeline添加ChannelHandler263
25.2.1 检查是否有重复的Handler265
25.2.2 创建节点266
25.2.3 添加节点271
25.2.4 回调用户方法272
25.2.5 ChannelPipeline添加ChannelHandler小结274
25.3 ChannelPipeline删除ChannelHandler274
25.3.1 找到待删除的节点275
25.3.2 调整双向链表指针并删除276
25.3.3 回调用户方法277
25.3.4 ChannelPipeline删除ChannelHandler小结278
25.4 Inbound事件的传播278
25.4.1 Unsafe是什么278
25.4.2 ChannelPipeline中的HeadContext282
25.4.3 ChannelPipeline中的Inbound事件传播289
25.4.4 ChannelPipeline中的TailContext291
25.4.5 Inbound事件的传播小结294
25.5 Outbound事件的传播294
25.6 ChannelPipeline中异常的传播299
25.6.1 Inbound异常的传播299
25.6.2 Outbound异常的传播301
25.7 总结302
第26章 writeAndFlush解析304
26.1 Pipeline中的标准链表结构304
26.2 Java对象编码过程305
26.3 write:写队列308
26.4 flush:刷新写队列311
26.4.1 获得第一个需要flush的节点的数据313
26.4.2 获得自旋锁的迭代次数314
26.4.3 采用自旋方式将ByteBuf写出JDK NIO的Channel314
26.4.4 删除该节点315
26.5 writeAndFlush:写队列并刷新316
26.6 总结317
第27章 本书总结319
27.1 Netty是什么319
27.2 服务端和客户端的启动319
27.3 ByteBuf320
27.4 自定义协议拆包与编解码320
27.5 Handler与Pipeline320
27.6 耗时操作的处理与统计321
27.7 最后的话321
· · · · · ·