首页 > 其他分享 >Tcp粘包半包问题(现实场景举例帮助理解)

Tcp粘包半包问题(现实场景举例帮助理解)

时间:2024-06-21 11:32:46浏览次数:9  
标签:02 接收端 报文 示例 Tcp 粘包 Length 半包 31

理解粘包问题时,我们可以将这个过程想象得更加生活化一些。想象你正在经营一家水果拼装店,你的任务是接收来自不同客户的水果订单,并将这些水果按照订单要求重新组装起来。每份订单中的水果都事先被切成了便于快递的“水果片”,并通过同一条传送带送过来。

现在,你收到了两份订单,一份是要拼装成一个完整香蕉的4片香蕉片,另一份是要分别拼装成一个苹果的5片苹果片和一个菠萝的6片菠萝片。但是,由于传送带不保证每次只送来自同一订单的水果片,你可能会遇到以下几种情况:

1. **粘包(Packet Concatenation)**:
   - 情景一:传送带上首先到达的是3片香蕉片紧接着跟着5片苹果片,然后才是剩下的1片香蕉片和全部的6片菠萝片。这意味着,本应分开的两份订单的部分内容“粘”在一起送达了,你需要仔细区分哪些香蕉片是属于第一个订单的,哪些是属于第二个订单的后续部分,以避免混淆。

2. **半包(Packet Fragmentation)**:
   - 情景二:第一次传送只给你送来了3片香蕉片,而苹果片和菠萝片完全没有送达。这代表你只收到了一个订单的一部分(即半包),你不得不等待剩余的香蕉片以及其他订单的水果片到达后,才能开始完整的组装工作。

简而言之,**粘包问题**是指在网络通信中,原本应该独立的数据包(在这里比喻为完整的水果订单)在传输过程中,其边界变得模糊,导致接收端难以准确区分不同消息的开始与结束,从而影响数据的正确解析。而**半包问题**则是指一个数据包的部分内容到达,而其余部分尚未到达,使得数据不完整,无法立即使用。

解决这些问题通常需要在应用层设计特定的协议来标记数据包的边界,比如通过添加包头包含长度信息、使用特定的分隔符、或者实现基于消息的传输协议等方法,确保接收方能够正确识别和重组接收到的数据片段。

下面我将通过几个示例来具体说明不同方法如何界定报文边界:

### 1. **TLV格式示例**

假设我们要发送一条包含用户ID的报文,其中:
- Tag: `0x01` 表示这是一个用户ID消息。
- Length: `0x04` 表示Value字段长度为4字节。
- Value: `0x31323334` 表示实际的用户ID数据,即字符串"1234"的ASCII码。

整个报文在二进制形式下看起来像这样(十六进制表示):
```
01 04 31 32 33 34
```
接收端首先读取Tag和Length,得知这是一个长度为4字节的用户ID报文,因此它会读取接下来的4字节作为实际的用户ID数据,即使这些数据与下一个报文的部分数据相邻接,也能准确分开。

### 2. **定长报文示例**

假设系统中所有报文都是100字节长度。发送端构造一个报文,无论是何种类型,都严格保证100字节。

接收端每次接收到100字节时,就直接认为是一个完整的报文,无需额外的报头信息来指示长度。这种方法简单直接,但不够灵活,不同类型或内容的报文无法轻易适应不同的长度需求。

### 3. **特殊分隔符示例**

假定使用`\n`(换行符)作为报文之间的分隔符。发送端在每个报文的末尾添加`\n`。

例如,发送两个报文,第一个报文内容为"Hello",第二个报文为"World!",实际发送的数据将是:
```
Hello\nWorld!\n
```
接收端读取数据时,每当遇到`\n`,就视为一个报文的结束,并开始处理新的报文。这种方法简单易行,但需要注意的是,如果报文内容中也可能包含分隔符本身,就需要额外的转义处理机制。

### 4. **序列号/报文编号示例**

每个报文前附加一个递增的序列号,如:
```
Seq: 01 | Data...
Seq: 02 | More data...
```
接收端通过检查序列号,确保按顺序接收报文,并可以检测丢失或重复的报文。这种方法增加了报文处理的复杂度,但提高了数据传输的可靠性。

以上就是几种界定报文边界的典型方法及其示例。每种方法都有其适用场景和优缺点,选择哪种方法取决于具体的应用需求。

下面我们重点了解下解决粘包半包问题的最佳实践TLV格式

TLV格式

  • Tag: 用于标识报文类型或内容的一个字段,帮助接收端识别接下来的数据是什么含义或用途。
  • Length: 表示紧随其后的Value字段的长度,即实际有效载荷数据的字节数。这个字段是关键,因为它告诉接收者报文的结束位置在哪里。
  • Value: 实际传输的数据内容,其长度由Length字段指定。

让我们通过几个TLV格式的示例,具体展示在可能出现粘包情况下的处理方法。粘包是指在TCP传输中,多个报文的数据在接收端可能被合并为一个数据包接收,或者一个报文的数据被拆分为多个数据包接收,导致接收端需要正确区分和解析每个独立的报文。

### 示例1:单个报文无粘包

假设发送两个独立的TLV报文,第一个是用户ID,第二个是用户年龄:

- 报文1(用户ID): `01 04 31 32 33 34` (Tag=01, Length=04, Value="1234")
- 报文2(用户年龄): `02 02 31 38` (Tag=02, Length=02, Value="18")

理想情况下,接收端先收到完整的报文1,然后是完整的报文2,直接根据Length字段解析即可。

### 示例2:粘包 - 同类报文连续

假设这两个报文连续发送,但在网络传输过程中被合并为一个数据包接收:
```
01 04 31 32 33 34 02 02 31 38
```
接收端接收到这段数据后,首先读取前6个字节(01 04 31 32 33 34),解析出一个完整的用户ID报文。之后,继续解析剩下的数据(02 02 31 38),识别为另一个完整的用户年龄报文。虽然数据粘包了,但由于每个报文内部有明确的Length字段,接收端仍能准确分离出各个报文。

### 示例3:粘包 - 部分报文和新报文混合

假设第一个报文(用户ID)的前半部分和第二个报文(用户年龄)同时到达:
```
01 04 31 32 02 02 31 38 33 34
```
这种情况下,首次接收的数据似乎没有完整的报文。但当第二次接收时,假设接收到剩余部分`33 34`,接收缓冲区现在为:
```
01 04 31 32 02 02 31 38 33 34
```
这时,接收端首先识别到完整的用户ID报文(01 04 31 32 33 34),处理后,余下的数据(02 02 31 38)构成一个完整的用户年龄报文。即使数据到达时部分报文交错,利用Length字段仍能正确解析。

### 示例4:拆包

考虑一个报文被拆分为两次接收的情况:
第一次接收:`01 04`
第二次接收:`31 32 33 34`
即使第一次接收的数据不足以构成一个完整报文,接收端可以暂时保存这部分数据。当第二次接收的数据到达,将其与之前保留的数据合并(01 04 31 32 33 34),这时根据Length字段解析出完整的用户ID报文。

通过这些示例,可以看出,即使在网络传输中出现数据包的粘包或拆包,利用TLV格式中的Length字段,接收端都能准确地识别出单个报文的边界,进而正确处理每个报文。

下篇讲解:在严重的数据包碎片化、网络拥塞导致的长时间延迟或数据丢失的场景下,Tag和Length都可能出现碎片化,如何解决

标签:02,接收端,报文,示例,Tcp,粘包,Length,半包,31
From: https://blog.csdn.net/koubeijingji/article/details/139826107

相关文章

  • TCP报文详解
    简介其实协议的形式就是结构化的数据,TCP协议也是,它的报头格式如下TCP报头,实际上是一个结构化的数据,也就是一个结构体。例如:structtcp_hdr{unsignedintstc_port:16;unsignedintdesc_port:16;unsignedintseq;unsignedintack_seq;....}......
  • 4.13 拔掉网线后, 原本的 TCP 连接还存在吗? (转载)
    4.13拔掉网线后,原本的TCP连接还存在吗?大家好,我是小林。今天,聊一个有趣的问题:拔掉网线几秒,再插回去,原本的TCP连接还存在吗?可能有的同学会说,网线都被拔掉了,那说明物理层被断开了,那在上层的传输层理应也会断开,所以原本的TCP连接就不会存在的了。就好像,我们拨打有线电话的......
  • TCP与UDP详解:层次、区别及应用场景
    TCP和UDP的层次及区别详解所属层次TCP(TransmissionControlProtocol,传输控制协议)和UDP(UserDatagramProtocol,用户数据报协议)都属于OSI模型中的传输层(第四层)。在传输层,协议的主要作用是为端到端的通信提供逻辑通信,并确保数据在网络上传输的可靠性和顺序。TCP和UDP的区别......
  • 不为人知的网络编程(十六):深入分析与解决TCP的RST经典异常问题
    本文由腾讯技术kernel分享,原题“TCP经典异常问题探讨与解决”,下文进行了排版和内容优化等。1、引言TCP的经典异常问题无非就是丢包和连接中断,在这里我打算与各位聊一聊TCP的RST到底是什么?现网中的RST问题有哪些模样?我们如何去应对和解决?本文将从TCP的RST技术原理、排查手段、......
  • 如何快速实现MODBUS TCP转Profinet---泗博网关EPN-330
    泗博网关EPN-330可作为PROFINET从站,支持与西门子S7-200SMART/300/400/1200/1500全系列PLC以及具有PROFINET主站的系统无缝对接,而ModbusTCP端,可以与ModbusTCP从站设备、主站PLC、DCS系统以及组态软件等进行数据交互。通过EPN-330,可以快速实现MODBUSTCP转Profinet,轻松地将多个M......
  • 【Android面试八股文】谈谈你对TCP 流量控制与拥塞控制的理解
    文章目录一、流量控制1.1流量控制的概念1.2滑动窗口1.3零窗口二、拥塞控制2.1拥塞控制的概念2.2慢启动2.3拥塞避免2.4快重传与快恢复2.4.1快重传2.4.2快恢复三、总结TCP的拥塞控制和流量控制虽然采取的动作很相似,但拥塞控制与网......
  • 浅谈配置元件之TCP取样器配置/TCP取样器
    浅谈配置元件之TCP取样器配置/TCP取样器1.引言在进行网络性能测试时,TCP取样器配置和TCP取样器(TCPSampler)是两个重要的组件,他们允许用户直接发送和接收TCP数据包,这对于测试服务器的TCP连接处理能力、模拟特定的TCP交互场景非常有用。本文档将详细介绍如何在JMeter中配......
  • tcp/ip 每层的协议
    TCP/IP网络通常是由上到下分成4层,分别是应用层,传输层,网络层和网络接口层。 网络接口层的传输单位是帧(frame),IP层的传输单位是包(packet),TCP层的传输单位是段(segment),HTTP的传输单位则是消息或报文(message) 一般说来,数据链路层发出的数据包称为frame,地址是链路层的地址,如mac地......
  • tcp 连接
    前言看到这个标题你可能会说,TCP连接的建立与断开,这个我熟,不就是三次握手与四次挥手嘛。且慢,脑海中可以先尝试回答这几个问题:四次挥手是谁发起的?如果断电/断网了连接会断开吗?什么情况下没有四次挥手连接也会断开?这不是面试,而是遇到了实际问题,至于是什么问题,容我先卖个关子,......
  • 八路DI八路DO开关量输入输出 远程IO模块 Modbus TCP数据采集模块 YL90
    特点:●八路开关量输入,八路开关量输出● DI状态变化自动发送状态数据,可以捕获脉冲● 采用Socket自由协议编程简单、轻松应用● 开关量毫秒级响应速度适应多种场合● 内置网页功能,可以通过网页查询与控制● 同时也支持ModbusTCP通讯协议● 宽电源供电范围:8~32......