Netty之第一次 TCP 连接时发生了什么

简介: Netty之第一次 TCP 连接时发生了什么

前言

在上一篇文章中我们详细的走了一遍bind()方法的启动流程, channel的初始化和注册, 并在初始化和注册的时候如果是第一次连接的话会执行pipeline.fireChannelActive();方法进行回调, 这次我们就对回调进行一次详细的讲解

从回调开始

前情回顾

重新带大家回顾一下上一篇文章末尾的知识, 我们进入了AbstractChannel类的register0方法, 这个方法是我们的channel调用注册和回调通知的地方

网络异常,图片无法展示
|

register0方法中重点关注上图中三个红框的地方:

  • doRegister(): 实际注册的方法
  • pipeline.fireChannelRegistered(); 回调方法
  • pipeline.fireChannelActive(); tcp 首次连接时调用, 也是本章的重点

tcp客户端首次连接服务端

网络异常,图片无法展示
|

我以debug模式启动Netty项目, 并在该方法上打了断点, 等待一会跳过断点, 可以看到控制台选中部分的时间和上一条打印日志时间间隔近30秒, 在放开debug之后执行了该方法, 调用回调打印

十二月 07, 2022 10:38:37 上午 io.netty.handler.logging.LoggingHandler channelActive
复制代码

剖析pipeline.fireChannelActive方法

一路Ctrl+左键查看方法详情, 下面注意一下图上的标记类名.方法名

DefaultChannelPipeline.fireChannelActive

网络异常,图片无法展示
|

AbstractChannelHandlerContext.invokeChannelActive

网络异常,图片无法展示
|

在该方法中, 我们可以看到不论最后执行结果是什么都会执行一个方法next.invokeChannelActive();, 那我们就进入这个方法看一下

AbstractChannelHandlerContext.invokeChannelActive

网络异常,图片无法展示
|

最后可以看到不论怎么执行他都会执行到channelActive()方法

  • 这个方法继承于ChannelInboundHandlerAdapter
  • ChannelInboundHandlerAdapter类中的channelActive()方法又继承于ChannelInboundHandler接口
  • 同时, 我们最开始DefaultChannelPipeline类下面还写了一个内部类HeadContext
  • HeadContext类中继承了ChannelInboundHandler也实现了该方法, 咱就说隐藏的真深, 我找半天...如下图

HeadContext类和channelActive()方法详情

网络异常,图片无法展示
|

网络异常,图片无法展示
|
这个类的继承图如下所示
网络异常,图片无法展示
|

所以回调到这里就差不多了, 别问我最后怎么理清的, debug大法好, 可能稍微有点乱, 大家最好自己debug走一遍, 再挨个类点开看一下

回调详情

DefaultChannelPipeline

网络异常,图片无法展示
|

网络异常,图片无法展示
|

**channel.read();**方法是Channel类的, 因为调用的channelNioServerSocketChannel, 所以我们直接去他的父类AbstractChannel中查看

NioServerSocketChannel 类的继承图

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

AbstractChannelread()方法进入到DefaultChannelPipelineread()方法

网络异常,图片无法展示
|

这样我们就找到了真正的read()方法, 到这里我们继续分析

findContextOutbound()

顾名思义, 这个方法是查找出栈的

网络异常,图片无法展示
|

这个方法详情流程如下:

  • 先是获取当前ChannelHandler
  • 获取当前ChannelHandlerexecutor
  • 获取前一个ChannelHandler
  • 判断执行while内的skipContext方法
  • skipContext方法的作用: 判断前一个ChannelHandler是否具有响应Write事件的资格

executor.inEventLoop()方法

判断当前线程是不是在当前的EventLoop中对应的那个线程

网络异常,图片无法展示
|

next.invokeRead()

直接进入这个方法查看一下, 神秘的面纱即将揭晓

网络异常,图片无法展示
|

有没有很熟悉的感觉, 在剖析pipeline.fireChannelActive方法的时候我们就碰到过类似的方法, 那个是invokeChannelActive()方法, 也是一个回调

网络异常,图片无法展示
|

因为handler == headContext, 所以最后就是调用的 handler.read()方法

回调执行结果

网络异常,图片无法展示
|

发现 doBeginRead() 方法

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

这里注意一下, 看到this.selectionKey了吗, 如果看我上一篇文章的小伙伴肯定会发现, 这不就是我们之前设置过得值吗

网络异常,图片无法展示
|

网络异常,图片无法展示
|

这一步就是重新为我们的selectionKey进行设置

结尾

本来想完成一下任务三的, 但是实在是搞不动了, 下一篇再说吧...

目录
相关文章
|
4月前
|
编解码 缓存 移动开发
TCP粘包/拆包与Netty解决方案
TCP粘包/拆包与Netty解决方案
45 0
|
2月前
|
网络协议
Netty实现TCP通信
Netty实现TCP通信
43 0
|
15天前
|
网络协议 Java 物联网
Spring Boot与Netty打造TCP服务端(解决粘包问题)
Spring Boot与Netty打造TCP服务端(解决粘包问题)
26 1
|
10月前
|
网络协议
netty编程实战02-创建一个带有连接重试的tcp客户端程序
netty编程实战02-创建一个带有连接重试的tcp客户端程序
161 0
|
9月前
|
网络协议 算法
Netty入门到超神系列-TCP粘包拆包处理
TCP是面向连接的,服务端和客户端通过socket进行数据传输,发送端为了更有效的发送数据,通常会使用Nagle算法把多个数据块合并成一个大的数据块,这样做虽然提高了效率,但是接收端就很难识别完整的数据包了(TCP无消息保护边界),可能会出现粘包拆包的问题。
65 0
|
10月前
|
网络协议 Java
netty编程实战01-创建一个tcp服务端程序
netty编程实战01-创建一个tcp服务端程序
201 0
|
11月前
|
存储 缓存 编解码
一文搞定Netty,打造单机百万连接测试!3
一文搞定Netty,打造单机百万连接测试!
|
11月前
|
设计模式 缓存 前端开发
一文搞定Netty,打造单机百万连接测试!2
一文搞定Netty,打造单机百万连接测试!
|
11月前
|
缓存 监控 网络协议
一文搞定Netty,打造单机百万连接测试!1
一文搞定Netty,打造单机百万连接测试!
|
11月前
|
消息中间件 缓存 网络协议
使用 Netty+SpringBoot 打造的 TCP 长连接通讯方案 下
使用 Netty+SpringBoot 打造的 TCP 长连接通讯方案 下