IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Netty接收超过1024字节 -> 正文阅读

[网络协议]Netty接收超过1024字节

应用场景

使用 Netty 创建 TCP 服务器,和底层硬件进行TCP 交互,底层每次传输1026个字节。

问题描述及复现

但是Netty的TCP服务端接收数据时,第一包只能接收1024个字节,第二包接收2字节。于是猜测是不是 Netty 有什么配置,将字节缓冲区设置成了 1024。于是到百度上查,有的人说将ChannelOption.SO_BACKLOG 设置成单次包传输的字节大小(在我这就是1026)。实际测试情况表明这并不是问题的解决办法。
于是我尝试着发送2056个字节过去,并打印每次接收的数据大小,结果如下
在这里插入图片描述

第一条日志是 1024 字节,第二条日志是 1032 字节。这两次实际上是底层硬件的第一次上传,被 Netty 分包了。
第三条日志对应客户端第二次上传数据
第四条日志对应客户端第三次上传数据

追踪问题原因

可以看到,对于客户端的三次数据上传,Netty 分配的缓冲区大小不是固定的!猜测可能是 Netty 为了节省内存开销而设计的这种机制,接下来进入断点定位问题。
在这里插入图片描述
可以看到这里有个 read 方法,估计和 jdk的 ServerSocket的read方法一个作用,点过去看看
在这里插入图片描述这里分配了一个 ByteBuf 正好是 1024 字节的容量,应该是在 allocHandle.allocate 方法中分配的空间。点进这个方法看看是如何分配的空间。
在这里插入图片描述
在这里插入图片描述可以看到 ioBuffer是根据参数来分配空间的,这样就可以定位到 guess()方法的返回值是关键。
F7步进到方法内部,可以看到这是一个AdaptiveRecvByteBufAllocator 的内部类,它返回一个成员属性nextReceiveBufferSize
在这里插入图片描述

它在被构建的时候指定了三个参数。而nextReceiveBufferSize就是在此处被初始化的。
在这里插入图片描述
getSizeTableIndex()是什么作用呢?可以到AdaptiveRecvByteBufAllocator 的 Doc 文档上看到这么一句话

在这里插入图片描述

这里可以看到,这个类就是实现可变缓冲区大小的。如果上次填满缓冲区,则下次会创建一个更大的缓冲区。Netty 在初始化时,创建了一个缓冲区大小空间值的数组。
在这里插入图片描述

在 Channel被创建时,会调用 AdaptiveRecvByteBufAllocatornewHandle 方法。此时指定的缓冲区大小默认为 1024
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

解决思路

如果说 Netty 默认提供了一个可变的缓冲区大小分配方案,那么我们可不可以改变这个策略呢?从AdaptiveRecvByteBufAllocator开始向上找到根类型,可以最终找到 RecvByteBufAllocator 接口上,查看这个接口的子类,应该会有其他缓冲区大小分配方案。
在这里插入图片描述
这里有一个固定的接收数组空间分配器,现在只要想办法把默认的 AdaptiveRecvByteBufAllocator换成 FixedRecvByteBufAllocator 就可以解决问题了。

现在回到 read 方法中,guess是在 allocate方法中调用的,而 allocate 则是一个RecvByteBufAllocator.Handle类型。

在这里插入图片描述
此时我们找到 recvBufAllocHandle()是如何创建这个 allocHandle的。
在这里插入图片描述

首先调用 config方法,然后调用getRecvByteBufAllocator来创建这个allocHandle。看下 config方法哪来的?
在这里插入图片描述

原来是在 Channel 中设置的呀,那既然有getRecvByteBufAllocator方法,那么肯定也有setRecvByteBufAllocator方法,我们在ChannelInitializer 中来调用下setRecvByteBufAllocator方法,并 new 一个FixedRecvByteBufAllocator来替换AdaptiveRecvByteBufAllocator
在这里插入图片描述

再次重启 Netty 的 Tcp 服务器,发现每次能够完整的接收到 1026字节,把 maxLen 改成 2056之后也是如此,问题解决!

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-01-04 13:46:39  更:2022-01-04 13:49:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 12:26:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码