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的数据包),那么就立刻发送该数据包。如果当前数据包m1<MSS,那么就会等到下一个数据包m2到来,如果该m1 + m2 > MSS,那么就会让将m2进行拆分发送。

  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.mzph.cn/diannao/68274.shtml

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

相关文章

websocket实现

由于安卓资源管理器展示的路径不尽相同,各种软件保存文件的位置也不一定一样.对于普通用户上传文件时,查找文件可能是一个麻烦的事情.后来想到了一个办法,使用pc端进行辅助上传. 文章目录 实现思路1.0 实现定义web与客户端通信数据类型和数据格式web端websocket实现web端对客户…

什么是反向海淘?如何入局反向海淘?

什么是反向海淘&#xff1f; 简单来说&#xff0c;反向海淘就是海外消费者通过国内的电商平台或独立站买入中国商品&#xff0c;然后通过跨境物流送到海外。以前是我们在国内买国外的东西&#xff0c;现在反过来&#xff0c;老外开始疯狂种草咱们的国货啦&#xff01; 为什么反…

leetcode刷题记录(一百)——121. 买卖股票的最佳时机

&#xff08;一&#xff09;问题描述 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09;121. 买卖股票的最佳时机 - 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票&#xff0c;并…

荔枝派LicheePi Zero V3S芯片图形系统开发详解[持续更新]

一、图形子系统 一般移动Linux设备实现图像显示的方案无非两种&#xff1a; 一种是使用OpenGL ES 另外一种就是使用FrameBuffer 使用OpenGL有个前提就是这个芯片是需要有GPU的&#xff0c;不然是没有意义的。 查看芯片系统框图&#xff0c;注意到V3S这款芯片是不支持GPU的…

AI刷题-最小化团建熟悉程度和

目录 问题描述 输入格式 输出格式 解题思路&#xff1a; 状态表示 状态转移 动态规划数组 预处理 实现&#xff1a; 1.初始化&#xff1a; 2.动态规划部分&#xff1a; &#xff08;1&#xff09;对于已分组状态的&#xff0c;跳过&#xff1a; &#xff08;2&…

使用Python和Qt6创建GUI应用程序---GUI的一个非常简短的历史

GUI的一个非常简短的历史 图形用户界面有着悠久而可敬的历史&#xff0c;可以追溯到20世纪60年代。斯坦福大学的NLS&#xff08;在线系统&#xff09;引入了鼠标和Windows概念于1968年首次公开展示。接下来是施乐PARC的Smalltalk系统GUI 1973&#xff0c;这是最现代的基础通用g…

DroneXtract:一款针对无人机的网络安全数字取证工具

关于DroneXtract DroneXtract是一款使用 Golang 开发的适用于DJI无人机的综合数字取证套件&#xff0c;该工具可用于分析无人机传感器值和遥测数据、可视化无人机飞行地图、审计威胁活动以及提取多种文件格式中的相关数据。 功能介绍 DroneXtract 具有四个用于无人机取证和审…

day7手机拍照装备

对焦对不上&#xff1a;1、光太暗&#xff1b;2、离太近&#xff1b;3、颜色太单一没有区分点 滤镜可以后期P 渐变灰滤镜&#xff1a;均衡色彩&#xff0c;暗的地方亮一些&#xff0c;亮的地方暗一些 中灰滤镜&#xff1a;减少光差 手机支架&#xff1a;最基本70cm即可 手…

【从零到一,C++项目实战】CineShare++(基于C++的视频点播系统)

&#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系列 &#x1f308;Linux学习专栏&#xff1a; 南桥谈Linux &#x1f308;数据结构学习专栏&#xff1a; 数据结构杂谈 &#x1f308;数据…

RabbitMQ 架构分析

文章目录 前言一、RabbitMQ架构分析1、Broker2、Vhost3、Producer4、Messages5、Connections6、Channel7、Exchange7、Queue8、Consumer 二、消息路由机制1、Direct Exchange2、Topic Exchange3、Fanout Exchange4、Headers Exchange5、notice5.1、备用交换机&#xff08;Alter…

九、CSS工程化方案

一、PostCSS介绍 二、PostCSS插件的使用 项目安装 - npm install postcss-cli 全局安装 - npm install postcss-cli -g postcss-cli地址&#xff1a;GitHub - postcss/postcss-cli: CLI for postcss postcss地址&#xff1a;GitHub - postcss/postcss: Transforming styles…

SpringBoot开发(二)Spring Boot项目构建、Bootstrap基础知识

1. Spring Boot项目构建 1.1. 简介 基于官方网站https://start.spring.io进行项目的创建. 1.1.1. 简介 Spring Boot是基于Spring4框架开发的全新框架&#xff0c;设计目的是简化搭建及开发过程&#xff0c;并不是对Spring功能上的增强&#xff0c;而是提供了一种快速使用Spr…

GESP2024年3月认证C++六级( 第三部分编程题(2)好斗的牛)

参考程序&#xff08;暴力枚举&#xff09; #include <iostream> #include <vector> #include <algorithm> using namespace std; int N; vector<int> a, b; int ans 1e9; int main() {cin >> N;a.resize(N);b.resize(N);for (int i 0; i &l…

SpringBoot统一数据返回格式 统一异常处理

统一数据返回格式 & 统一异常处理 1. 统一数据返回格式1.1 快速入门1.2 存在问题1.3 案列代码修改1.4 优点 2. 统一异常处理 1. 统一数据返回格式 强制登录案例中,我们共做了两部分⼯作 通过Session来判断⽤⼾是否登录对后端返回数据进⾏封装,告知前端处理的结果 回顾 后…

Elasticsearch+kibana安装(简单易上手)

下载ES( Download Elasticsearch | Elastic ) 将ES安装包解压缩 解压后目录如下: 修改ES服务端口&#xff08;可以不修改&#xff09; 启动ES 记住这些内容 验证ES是否启动成功 下载kibana( Download Kibana Free | Get Started Now | Elastic ) 解压后的kibana目…

十年筑梦,再创鲸彩!庆祝和鲸科技十周年

2025 年 1 月 16 日&#xff0c;“十年筑梦&#xff0c;再创鲸彩” 2025 和鲸科技十周年庆暨 2024 年终表彰大会圆满落幕。 十年征程&#xff0c;和鲸科技遨游于科技蓝海&#xff0c;破浪前行&#xff0c;无惧风雨。期间所取得的每一项成就&#xff0c;都凝聚着全体成员的智慧结…

【Uniapp-Vue3】动态设置页面导航条的样式

1. 动态修改导航条标题 uni.setNavigationBarTitle({ title:"标题名称" }) 点击修改以后顶部导航栏的标题会从“主页”变为“动态标题” 2. 动态修改导航条颜色 uni.setNavigationBarColor({ backgroundColor:"颜色" }) 3. 动态添加导航加载动画 // 添加加…

openlayer getLayerById 根据id获取layer图层

背景&#xff1a; 在项目中使用getLayerById获取图层&#xff0c;这个getLayerById()方法不是openlayer官方文档自带的&#xff0c;而是自己封装的一个方法&#xff0c;这个封装的方法的思路是&#xff1a;遍历所有的layer&#xff0c;根据唯一标识【可能是id&#xff0c;也可能…

Unity入门2 背景叠层 瓦片规则

切割场景 瓦片调色盘 放在Assets里面新建瓦片地图,palettes tile 瓦片 palettes调色板 上下窗口是分开的 拖进这个格子窗 瓦片太碎&#xff0c;要封装 装好之后&#xff0c;只是把瓦片放上去了&#xff0c;但是还没有画布&#xff0c;显示是这样的 no valid target 新建“…

Kafka 日志存储 — 日志清理

Kafka 提供两种日志清理策略&#xff1a;日志清理(Log Delete)与日志压缩(Log Compaction)。 1 日志清理 通过broker端参数log.cleanup.policy来设置日志清理策略&#xff0c;默认值为“delete”。如果要采用日志压缩的清理策略&#xff0c;则设置为“compact”。可以同时支持…