Netty粘包与拆包

文章首发地址

  • TCP是一个“流”协议。所谓流,就是没有界限的一长串二进制数据。
  • 拆包和粘包:TCP作为传输层协议,并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认为是一个完整包的,可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP拆包和粘包问题。
  • 半包:Netty在轮询读事件的时候,每次从Channel中读取的数据,不一定是一个完整的数据包,这种情况就叫作半包。
  • 粘包:Client往Server发送数据包时,如果发送频繁很有可能会将多个数据包的数据都发送到通道中,Server在读取的时候可能会读取到超过一个完整数据包的长度,这种情况叫作粘包。

TCP 粘包/拆包问题说明

假设客户端分别发送了两个数据包 Dl 和 D2 给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下 4 种情况。

  1. 服务端分两次读取到了两个独立的数据包,分别是 D1 和 D2,没有粘包和拆包;
  2. 服务端一次接收到了两个数据包, D1 和 D2 粘合在一起,被称为 TCP 粘包;
  3. 服务端分两次读取到了两个数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为 TCP 拆包;
  4. 服务端分两次读取到了两个数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余内容D1_2和D2包的整包。

TCP 粘包/拆包发生的原因

问题产生的原因有三个,分别如下。

  1. 应用行序write 写入的字节大小大于套接日发送缓冲区大小;
  2. 进行 MSS 大小的 TCP 分段;
  3. 以太网帧的payload 大于MTU进行IP分片

粘包问题的解决策略

  1. 消息定长,报文长度固定,例如每个报文的长度固定为200字节,如果不够空位补空格。
  2. 报尾添加特殊分隔符,例如每条报文结束都添加回车换行符(如FTP)或者指定特殊字符作为报文分隔符,接收方通过特殊分隔符区分报文。
  3. 将消息分为消息头和消息体,消息头包含表示信息的总长度(或者消息体长度)的属性。
  4. 更复杂的自定义应用层协议。
    Netty对半包或者粘包的处理:每个Handler都是和Channel唯一绑定的,一个Handler只对应一个Channel,所以Channel中的数据读取的时候经过解析,如果不是一个完整的数据包,则解析失败,将这个数据包进行保存,等下次解析时再和这个数据包进行组装解析,直到解析到完整的数据包,才会将数据包向下传递。

利用LineBasedFrameDecoder解决TCP粘包问题

LineBaseFrameDecoder的工作原理是它依次遍历ByteBuf中的可读下节,判断否有“\n”或者"\r\n", 如果有,就以此位置为结束位置,从可读索引到结束位置区间的字节就组成了一行。它是以换行符为结束标志的解码器,支持携带结束符或者不携带结束符两种解码方式,同时支持配置单行的最大长度。如果连续读取到最大长度后仍然没有发现换行符,就会抛出异常,同时忽略掉之前读到的异常码流。

StingDecoder的功能日常间单,就是将接收到的对象转换成字符串,然后继续调用后面的Handler。LineBasedFrameDecoder + String Decoder组合就是按行切换的文本解码器,它被设计用来支持 TCP 的粘包和拆包。

同时也支持其他的解码器,以满足不同诉求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何正确有效的学习java前端(合集)

大量阅读 我是一个劲头十足的读者。所以,我的第一个关于学习JavaScript的技巧就是关于阅读,这绝不是巧合。书籍和其他的资源(如文章)可以在很大程度上帮助你学习JavaScript。通过实践学习,书籍是我学习新学科最喜欢的方式。在学习JavaScript的…

测试用例(2)

项目管理工具 主要用tapd,jira少用 acp 敏捷项目管理证书 task:故事,一个故事有开始也有结束,那么在项目管理里面,会把每个任务按照一个task来看,那么这个task也可以叫story,具体指的就是任务有开始有结…

ChatGPT火热之下的冷思考

作为一款基于人工智能的自然语言处理(NLP)​​聊天机器人​​程序,ChatGPT通过大量来自互联网的文本进行训练,并使用深度学习和机器学习算法来理解用户的问题并提供准确的回答。并且,ChatGPT还内置了情感分析、关键字提取和实体识别等功能&am…

Beyond Compare 代码比较工具

一、下载 官网下载地址: https://www.scootersoftware.com/download.php 选择 Windows 系统,简体中文版本,点击下载。 下载完成 二、安装 步骤1:双击安装包 步骤2:进入安装向导,点击下一步 步骤3&a…

Linux的scp命令使用详解

scp 是 Linux 中用来复制文件的命令。它是基于 SSH 协议的,可以在本地主机和远程主机之间复制文件。命令的语法是:scp [options] [source_file] [destination]。 常用的[options]选项包括-r(递归复制目录)和-P(指定连…

Ubuntu 20 开机免密root登录

首先如果没有设置root密码,先设置一下root用户的密码:sudo passwd root 一条命令打开所有需要修改的文档: sub /root/.profile /etc/pam.d/gdm-autologin /etc/pam.d/gdm-password /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf /etc/…

在LLM的支持下使游戏NPC具有记忆化的方法

问题 使用GPT这样的LLM去处理游戏中的NPC和玩家的对话是个很好的点子,那么如何处理记忆化的问题呢。 因为LLM的输入tokens是有限制的,所以伴随着问题的记忆context是有窗口大小限制的,将所有的记忆输入LLM并不现实。 所以这里看到了stanfo…

Zookeeper

作为分布式中间件,zookeeper有以下几个重要功能 服务注册服务监听 :观察者模式,有服务上线或下线可以感知,并进行响应回调处理服务拉取配置中心CP特性数据存储方式为标准的文件结构 安装zk需要java环境,可参考 linux…

面试中关于自动化测试的认识

目录 一、什么是自动化测试,自动化测试的优势是什么? 二、什么样的项目比较适合做自动化测试,什么样的不适合做自动化测试? 三、在制定自动化测试计划的时候一般要考虑哪些点? 四、编写自动化脚本时的一些规范&…

怎么给pdf文件加密?pdf文档如何加密

在数字化时代,保护个人和机密信息的重要性越来越受到关注。PDF(Portable Document Format)是一种广泛使用的文件格式,用于共享和存储各种类型的文档。然而,由于其易于编辑和复制的特性,保护PDF文件中的敏感…

xss跨站脚本攻击总结

XSS(跨站脚本攻击) 跨站脚本攻击(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets )CSS的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当…

css基本样式的使用

1、高度和宽度 .c1{height: 300px;width: 500px; }注意事项: 宽度,支持百分比行内标签,默认无效块级标签,默认有效(即使右侧空白,也不给你占用) 块级和行内标签 css样式 标签: di…

我在VScode学Java(Java方法method)

​ 我的个人博客主页:如果’真能转义1️⃣说1️⃣的博客主页 关于Java基本语法学习---->可以参考我的这篇博客:《我在VScode学Java》 关于Java数组学习、JVM中的堆和栈—>可以参考我的这篇文章我在VScode学Java(Java一维数组、二维数组、JVM中的堆…

Android JNI线程的同步 (十三)

🔥 Android Studio 版本 🔥 🔥 了解线程同步的两个变量 🔥 pthread_mutex_t 互斥锁 线程的互斥: 目前存在两个线程 , 线程A和线程B, 只允许只有一个资源对临界资源进程操作 (大概意思就是 : A线程 进入操作临界资源的时候 , 那么 B线程 就要进行等待 . 等到 A线程…

Spark(22):SparkStreaming之DStream创建

目录 0. 相关文章链接 1. RDD队列 1.1. 用法及说明 1.2. 案例实操 2. 自定义数据源 2.1. 用法和说明 2.2. 案例实操 3. Kafka数据源 3.1. 版本选型 3.2. Kafka 0-8 Receiver 模式(当前3.x版本不适用) 3.3. Kafka 0-8 Direct 模式(…

离线安装docker

目录 1、下载docker 安装包 2、上传docker 到服务器目录/opt/ 3、解压docker-19.03.9.tgz 4、解压的docker文件夹全部移动至/usr/bin目录 5、将docker注册为系统服务 6、重启生效 6.1、重新加载配置文件 6.2、启动Docker服务 6.3、查看启动状态 6.4、 设置docker为开…

CS 144 Lab Two -- TCPReceiver

CS 144 Lab Two -- TCPReceiver TCPReceiver 简述索引转换TCPReceiver 实现 测试 对应课程视频: 【计算机网络】 斯坦福大学CS144课程 Lab Two 对应的PDF: Lab Checkpoint 2: the TCP receiver TCPReceiver 简述 在 Lab2,我们将实现一个 TCPReceiver,用…

如何在Ubuntu上安装OpenneBula

OpenNebula是一个开源云计算平台,允许我们在完全虚拟化云中组合和管理VMware和KVM虚拟机 第1步:安装MariaDB数据库服务器 OpenNebula还需要一个数据库服务器来存储其内容。 安装MariaDB: 1 2 sudo apt update sudo apt install mariadb-s…

mac idea 常用快捷键

mac idea 常用快捷键 代码生成: Command N:在代码编辑界面生成setter、getter等代码。当光标在左侧的工程结构时,使用Command N可以创建新的类、包等。 删除和复制: Command Delete:删除当前行。Command D&#…

SringCloud集成Redis工具类

1、pom文件 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2、redis工具类 Service(value "redisService") Slf4j public class RedisServi…