Linux之Tcp粘包笔记

目录

一.网络传输四层模型

二.数据传输中数据包传输的两个限制概念

 三.数据传输的中粘包问题

四.数据组装的原因

Nagle算法原理:

五.关闭Nagle优化处理粘包问题吗?

六.粘包处理方法

a.设置消息边界:

b.定义消息长度:

七.UDP是否会出现粘包

a.IP数据报文格式

 b.UDP数据报文格式

c.tcp数据报文格式

八.IP层网络层是否会产生粘包

九总结


一.网络传输四层模型

在网络传输的四层模型中:网络层接口(数据链路层)->网络层->传输层->应用层。通过这四层模型传递,进行数据传输。如下图:

发送方传递消息,经过每一层都添加对应模型的包头,在传递下一等模型,接收方接收到通过层层剥离每一层的包头,最后就得到对应的消息。

二.数据传输中数据包传输的两个限制概念

MTU:最大传输单元(这个由网络接口层决定,最大为1500字节)。

MSS:最大传输报文(表示每次传输的报文大小)表示tcp用来限制应用层每次最大发送的报文长度。

两者关系: MTU = MSS + IP(头部,20字节) + TCP(头部,20字节)

例如:如果一个报文长度< 1500,那么一次就可以发送完成。> 1500 的报文传输就需要进行分片传输。比如,2000长度的数据包,第一个分包:1460,第二个分包:540(剔除ip+tcp包头各占20个字节)

如下图,MTU跟MSS关系图解:

 三.数据传输的中粘包问题

      针对粘包的产生,产生在TCP(字节流传输),例如:a给b发送一条消息,HelloWorld。可是因为传输过程中,b接受到的信息:HelloW ,orld这样b接收到的信息就变了意思。为什么会产生此种情况。就是因为所说的粘贴包导致。

   原因:TCP传输按照字节流传输(传输的就是二进制的数据流),在下层发送的时候,可能会被切片并且重新组装,最后再发送至接收者的缓冲区,而接收端未能正确的还原对应的数据流导致。这种情况的粘包问题主要是出在了开发者对tcp数据字流的处理上。并非tcp传输方式自身会产生粘包,这个才是出现粘包的实质原因。

四.数据组装的原因

        因为受限于MTU跟MSS的报文传输限制,当要传输一个很大的报文时,就需要对该报文进行分割,将其分割成若干,依次通过限制的传输通道,接收方收到后,再将收到的分割包重新组装起来,还原发送方的数据。另外在Tcp的传输方式中还存在一个组装的情况。比如,发送两个比较小的数据报文(<MSS),这样的发送方式比较比较浪费资源。所以TCP中设计了优化算法,Nagle算法进行优化。

Nagle算法原理:

  a.在发送一个数据包如果长度达到MSS(or含有FIN的数据包),那么就立刻发送该数据包。如果当前数据包msg1<MSS,那么就会等到下一个数据包msg2到来,如果该msg1 + msg2 > MSS,那么就会让将msg2进行拆分发送。

  b.该算法每次发送数据包,(设置了一个超时等待机制,一般是200ms),第一个包长度没达到MSS,就会进行一个超时等待第二个包来,如果等待第二个包超时还没来,则立刻发送第一个数据包。

c.如下图解:

d.m1 < MSS,此时m2来了,但是len(m1+ m2) > MSS,在Nagle算法开启情况,会将m2进行拆分,m2-1,m2-2,此时len(m1 + m2-1)= MSS,将该两包进行组装并且立刻发送出去。而m2-2,会重复前面的流程等待(200ms),以此类推,如果超时还没等到包来,就立刻将当前包发送出去。

e.上图解释明确颜色表述,但实际存储的都是为二进制数据,如果接受者把m1+ m2-1,当成一个包来处理,就会造成不明消息,该情况就是粘包情况。

五.关闭Nagle优化处理粘包问题吗?

    a.Nagle算法优化了资源的浪费情况,但是带来粘包问题。另外超时等待机制也是一个很大的缺陷问题,比如当下的游戏场景,正在打游戏,因为该算法的超时等待,导致一个数据包延时到来,就会造成游戏画面卡顿。通常使用中,都会关闭该算法优化。TCP_NODELAY = 1(Nagle关闭)

    b.即便关闭了该算法的优化,是不是就不会产生粘包情况?答案是否定的。仍旧会产生粘包问题。如下图:

如图,当m1消息到来时,直接取走了,消息正常还原。然后后续有消息来了,发送到了接受方的缓冲区,因应用层未能及时读走,下一个数据包也发送到了接受方的缓冲期如上图m2m3, 此时应用层一次将所有的数据读取了,导致数据混乱,从而导致就出现了粘包问题,

六.粘包处理方法

       粘包的问题主要是字节流传输中未能定义具体的消息边界导致。换句话说就是开发者发送数据的问题导致。如下介绍几种方法:

a.设置消息边界:

        给消息定义边界头跟边界尾巴,消息结构如下:

    |消息头|消息体|消息尾||header|body| body_tail|

 但是a中存在一个问题,如果消息内容中存在跟头or尾中一样的标志,也会出现问题,处理该问题,可采用crc校验和添加来处理,如下图解:

        校验和:对整个消息生成的校验值

发送方通过对消息设置对应的校验和,接收方收到消息后,校验确保是发送方发送的完整数据。

b.定义消息长度:

        利用消息长度,应用层再度读取消息的按照消息长度读取正确的消息内容,跟http中的Content-Length表示传输的数据长度蕾丝。该种方法,也可结合a中的标志,再加上消息长度,就更加的能确保消息的读取的正确性。

结构如下:

七.UDP是否会出现粘包

       首先UDP的发送方式,使用的是数据报文方式,每次发送的数据都是一整个数据报文。无论应用层每次丢给UDP的报文多长,都会原样发送出去。这是跟tcp按照字节流发送的差异性。另外如果UDP的数据太大的话,也是会进行分片的,只不过该分片在IP层面,即便在应用层面,也不会像tcp那样分不清啥时候会结束。这就是udp跟tcp两者的区别。例如发送端发送了10次,接受端接收10次,发多少,接收多少,确保每次一完成的数据包就好了。

a.IP数据报文格式

 上图中有个16位的总长度,表明Ip包的总长度m。

 b.UDP数据报文格式

 如上图,UDP报文头有个16位的UDP长度表示n。应用层可根据该字段,读取对应大小的UDP报文。故而UDP不会产生粘包问题。另外如果不存在长度n,那么通过ip层也能够知道udp数据报文长度。计算方式: UDP包长度 = IP包总长度 - IP包头部 - UDP包头部。有个问题,这个16位的n字段是否多余的。如下答案:

c.tcp数据报文格式

 如上图tcp的报文结构中没有存储数据包的长度,但是依旧能通过如下方式计算:

tcp包长度 = IP包长度 - IP包头长度 - TCP包长度,如下图:

上面说UDP数据包头中的16位长度是否多余呢?答案否定的。如下解释:Tcp-Ip卷2中解释说是用于计算校验和,并且说UDP底层可能用的不是Ip协议,如果是其他网络类型,那么就不能计算UDP包长度了。但是还有一种解释,根据某位大佬的讲解,因为IP层是网络层协议,而UDP是传输层协议,当数据传输层,此时IP层头部已经被剥离了,此时如果UDP没有自身16位的长度,是无法计算出数据部分长度的。所有该解释感觉比较更切近点。当前卷中的解释,可能以后出现新协议作网络层处理,也是可能的。敬请期待中。。。还有,这个n跟tcp中应用层定义对应数据包长度字段是一个道理,用来确定包长度,防止粘包发生。

八.IP层网络层是否会产生粘包

  IP层传输也会对大包进行分包处理的,那么是否会产生粘包呢?

  答案是不会产生粘包的。这个前面说了,粘包的原因是使用者无法正确区分消息边界导致的。如下图所示:

整个数据包传输过程,从发送者网络层到接受者网络层,消息太长,超过MTU,会把消息分N个切片,并且每个切片会携带自身在整包的位置偏转量(offset)以及相同的头部信息。当数据包到达接受者的网络层,会将数据包重新组装起来。(过程是申请一个ip结构,将所有的分片包按照偏转量放置在各自的位置)等所有数据包组装完成,再即将数据包推到传输层。后面的处理,就是如上解释的是否粘包问题以及相关的处理。另外有关IP层分片请见如下博文,上图来自博主的下述文章:网络层协议之IP数据包层分片随笔_ip数据报分片计算-CSDN博客

九总结

         粘包的问题归根结底是开发者,未能正确区分消息边界导致,跟协议并无多大关系。

        a.TCP无论发送送什么,都是字节流发送,可能当前的字节流存在上次数据发送的内容,(就是粘包),只要使用消息边界确认就可以避免粘包。

        b.TCP有Nagle算法会导致粘包问题,但是关闭该算法并不解决粘包问题。

        c.UDP基于数据报文传输,不会产生粘包问题。

        d.IP层也会进行包分片,但仅仅是网络进行传输,并不关心数据包内容是什么,所以不会有粘包问题。

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

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

相关文章

【C语言算法刷题】第2题 图论 dijkastra

题目描述 一个局域网内有很多台电脑&#xff0c;分别标注为 0 ~ N-1 的数字。相连接的电脑距离不一样&#xff0c;所以感染时间不一样&#xff0c;感染时间用 t 表示。 其中网络内一台电脑被病毒感染&#xff0c;求其感染网络内所有的电脑最少需要多长时间。如果最后有电脑不…

软件测试压力太大了怎么办?

本文其实是知乎上针对一个问题的回答&#xff1a; 目前在做软件测试&#xff0c;主要负责的是手机端的项目测试&#xff0c;项目迭代很快&#xff0c;每次上线前验正式都会发现一些之前验测试包时候没有发现的问题&#xff0c;压力太大了&#xff0c;应该怎么调整 看过我之前其…

枚举与模拟 练习

练习题基于《C/C程序设计竞赛真题实战特训教程&#xff08;图解版&#xff09;》 目录 1.1 卡片 题目描述 代码实现 题解笔记 总评 注意点 重点解释 1.2 回文日期 题目描述 输入描述 输出描述 代码实现 题解笔记 总评 注意点 重点解释 1.1 卡片 题目描述 小蓝…

Redis高阶5-布隆过滤器

Redis布隆过滤器 ​ 由一个初始值都为零的bit数组和多个哈希函数构成&#xff0c;用来快速判断集合中是否存在某个元素 目的减少内存占用方式不保存数据信息&#xff0c;只是在内存中做一个是否存在的标记flag 布隆过滤器&#xff08;英语&#xff1a;Bloom Filter&#xff0…

vim如何设置自动缩进

:set autoindent 设置自动缩进 :set noautoindent 取消自动缩进 &#xff08;vim如何使设置自动缩进永久生效&#xff1a;vim如何使相关设置永久生效-CSDN博客&#xff09;

检测到联想鼠标自动调出运行窗口,鼠标自己作为键盘操作

联想鼠标会自动时不时的调用“运行”窗口 然后鼠标自己作为键盘输入 然后打开这个网页 &#xff08;不是点击了什么鼠标外加按键&#xff0c;这个鼠标除了左右和中间滚轮&#xff0c;没有其他按键了&#xff09;

(Halcon)轮廓等分切割(项目分析)

目标&#xff1a;获取绿色圆所在位置&#xff08;可用于点焊/点胶引导&#xff09; 实现思路 一&#xff0c;相机标定板标定&#xff08;如果实战用于点焊/点胶引导需要做图像畸变校正以减小误差&#xff09; 相机标定 如何做一个C#仿Halcon Calibration插件-CSDN博客 二&…

Java面试题2025-Mysql

1.什么是BufferPool&#xff1f; Buffer Pool基本概念 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP。其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。 Buffer Pool由缓存数据页(Page) 和 对缓存数据页进行描述的控制块 组成, 控制…

开始步入达梦中级dba

分析内存使用需要的方法之一 disql /nolog conn sysdba/sysdbaselect value from v$parameter where nameMEMORY_LEAK_CHECK; SP_SET_PARA_VALUE(0,MEMORY_LEAK_CHECK,1); select * from V$MEM_REGINFO; select * from V$MEM_HEAP;

UE求职Demo开发日志#7 强化属性完善

1 实现思路设计 定义一个结构体记录技能树一个单元的信息&#xff0c;命名为FStrengthenCellInfo&#xff0c;一个TArray记录技能树整体信息&#xff0c;需要以下信息&#xff1a; 1.TArray前置技能index 2.FString 描述文本 3.TArray<FMyItemInfo>激活需要的物品ID和…

Qt中QVariant的使用

1.使用QVariant实现不同类型数据的相加 方法&#xff1a;通过type函数返回数值的类型&#xff0c;然后通过setValue来构造一个QVariant类型的返回值。 函数&#xff1a; QVariant mainPage::dataPlus(QVariant a, QVariant b) {QVariant ret;if ((a.type() QVariant::Int) &a…

做Midjourney最好图文教程-提示词公式以及高级参数讲解

先说Midjourney万能公式 填写在绘图提示词框里的内容就是提示词&#xff0c;也叫prompt 用途&#xff1a;让Midjourney生成对应图片&#xff08;符合提示词所描述内容的图片&#xff09;&#xff0c;控制图片生成方向种类&#xff1a;文本提示、图像提示、参数提示&#xff0…

【论文阅读】RAG-Reward: Optimizing RAG with Reward Modeling and RLHF

研究背景 研究问题&#xff1a;这篇文章要解决的问题是如何优化检索增强生成&#xff08;RAG&#xff09;系统&#xff0c;特别是通过奖励建模和人类反馈强化学习&#xff08;RLHF&#xff09;来提高大型语言模型&#xff08;LLMs&#xff09;在RAG任务中的效果。研究难点&…

《Trustzone/TEE/安全从入门到精通-标准版》

CSDN学院课程连接:https://edu.csdn.net/course/detail/39573 讲师介绍 拥有 12 年手机安全、汽车安全、芯片安全开发经验,擅长 Trustzone/TEE/ 安全的设计与开发,对 ARM 架构的安全领域有着深入的研究和丰富的实践经验,能够将复杂的安全知识和处理器架构知识进行系统整…

Pyecharts之地图图表的强大功能

在数据可视化领域中&#xff0c;地图图表是一种强大的工具&#xff0c;能够直观地展现与地理位置相关的数据信息&#xff0c;帮助我们更好地洞察数据的地域特征和分布规律。Pyecharts 为我们提供了丰富的地图图表功能&#xff0c;让我们可以轻松实现各种地理信息的可视化展示。…

政安晨的AI大模型训练实践三:熟悉一下LF训练模型的WebUI

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 目录 启动WebUI 微调模型 LLaMA-Factory 支持通过 WebUI 零代码微调大语言模型。 启动Web…

【2024年华为OD机试】(A卷,200分)- 创建二叉树 (JavaScriptJava PythonC/C++)

一、问题描述 构建二叉树并返回根节点 题目描述 请按下列描述构建一颗二叉树,并返回该树的根节点: 先创建值为-1的根结点,根节点在第0层;然后根据operations依次添加节点:operations[i] = [height, index] 表示对第 height 层的第 index 个节点 node,添加值为 i 的子节…

有限元分析学习——Anasys Workbanch第一阶段_终篇_齿轮整体强度案例分析

目录 0 序言 1 齿轮整体强度分析案例 1.1 模型简化 1.2 前处理 1&#xff09;分析类型选择 2&#xff09;设置平面参数 3&#xff09;约束、载荷及接触 2 控制网格 a.初次生成网格&#xff0c;对局部网格不做控制 b.第一次调整接触网格&#xff0c;接触面网格控制为…

Final2x--开源AI图片放大工具

Final2x--开源AI图片放大工具 链接&#xff1a;https://pan.xunlei.com/s/VOHSklukQAquUn3GE7eHJXfOA1?pwdr3r3#

【由浅入深认识Maven】第2部分 maven依赖管理与仓库机制

文章目录 第二篇&#xff1a;Maven依赖管理与仓库机制一、前言二、依赖管理基础1.依赖声明2. 依赖范围&#xff08;Scope&#xff09;3. 依赖冲突与排除 三、Maven的仓库机制1. 本地仓库2. 中央仓库3. 远程仓库 四、 版本管理策略1. 固定版本2. 版本范围 五、 总结 第二篇&…