JavaDriver JavaDriver
首页
  • 基础
  • 并发
  • JVM
  • 设计模式
  • 计算机网络
  • 操作系统
  • 数据结构
  • 算法
  • MYSQL
  • REDIS
  • Netty
  • Kafka
系统设计
非技术
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

YoungAnn

西二旗Java老司机一枚 致力于社会主义添砖Java
首页
  • 基础
  • 并发
  • JVM
  • 设计模式
  • 计算机网络
  • 操作系统
  • 数据结构
  • 算法
  • MYSQL
  • REDIS
  • Netty
  • Kafka
系统设计
非技术
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机网络

    • 简述 TCP 三次握手以及四次挥手的流程。为什么需要三次握手以及四次挥手?
    • 简述常见的 HTTP 状态码的含义
    • 从输入 URL 到展现页面的全过程
    • HTTP 中 GET 和 POST 区别
    • TCP 怎么保证可靠传输
    • 什么是 TCP 粘包和拆包?
      • TCP粘包与拆包
      • 粘包和拆包原因
      • 粘包和拆包解决策略
      • 粘包的概念
      • 出现粘包的原因
      • 粘包的处理方式
    • 简述 HTTPS 的加密与认证过程
    • 简述对称与非对称加密的概念
    • TCP 与 UDP 在网络协议中的哪一层,他们之间有什么区别?
    • 如何解决 TCP 传输丢包问题?
    • TCP 长连接和短连接有那么不同的使用场景?
    • TCP 的 keepalive 了解吗?说一说它和 HTTP 的 keepalive 的区别?
    • HTTP 与 HTTPS 有哪些区别?
    • TCP 中常见的拥塞控制算法有哪些?
    • 简述 HTTP 1.0,1.1,2.0 的主要区别
    • 从系统层面上,UDP如何保证尽量可靠?
    • TCP 挥手时出现大量 CLOSE_WAIT 或 TIME_WAIT 怎么解决?
    • 简述 TCP 滑动窗口
    • 简述TCP重传机制
    • 简述 JWT 的原理和校验机制
    • 为什么需要序列化?有什么序列化的方式?
    • 简述 iPv4 和 iPv6 的区别
    • TCP 中 SYN 攻击是什么?如何防止?
    • 简述 DDOS 攻击原理,如何防范它?
    • 什么是 ARP 协议?简述其使用场景
    • 什么是跨域,什么情况下会发生跨域请求?
    • Cookie 和 Session 的关系和区别是什么?
    • 简述 WebSocket 是如何进行传输的
    • DNS 查询服务器的基本流程是什么?DNS 劫持是什么?
    • RestFul 是什么?RestFul 请求的 URL 有什么特点?
    • 简述 HTTP 报文头部的组成结构
  • 操作系统

  • 数据结构

  • 算法

  • 剑指Offer题解

  • 计算机基础
  • 计算机网络
YoungAnn
2022-09-21
目录

什么是 TCP 粘包和拆包?

# TCP粘包与拆包

TCP是个“流”协议,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

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

(1)服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包;

(2)服务端一次接收到了两个数据包,D1和D2粘合在一起,被称为TCP粘包;

(3)服务端分两次读取到了两个数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为TCP拆包;

(4)服务端分两次读取到了两个数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余内容D1_2和D2包的整包。

如果此时服务端TCP接收滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种可能,即服务端分多次才能将D1和D2包接收完全,期间发生多次拆包。

# 粘包和拆包原因

(1)要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;

(2)接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;

(3)要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;

(4)待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。

# 粘包和拆包解决策略

由于底层的TCP无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,归纳如下:

消息定长。发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

设置消息边界。服务端从网络流中按消息边界分离出消息内容。在包尾增加回车换行符进行分割,例如FTP协议。

将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段。 更复杂的应用层协议。

# 粘包的概念

粘包:多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界,而采用某一估测值大小来进行数据读出,若双方的size不一致时就会使指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

比如说:发送方发送了两个数据,接收方一次收了一个半数据(接收方可能不清楚一个包有多大)

# 出现粘包的原因

出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。

发送方引起的粘包是由TCP协议本身造成的:

TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。

TCP协议规定有MSS,如果数据包过长就会被分开传输。这样接收方就收到了拆包数据。

接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。

在代码中常见体现:

要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。

要发送的数据大于MSS,TCP在传输前将进行拆包。

要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。

接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。 等等。

# 粘包的处理方式

当短连接的情况下,不用考虑粘包的情况

如果发送数据无结构,如文件传输,这样发送方只管发送,接收方只管接收存储就ok,也不用考虑粘包

如果双方建立长连接,需要在连接后一段时间内发送不同结构数据

发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

编辑 (opens new window)
上次更新: 2022/09/26, 09:00:38
TCP 怎么保证可靠传输
简述 HTTPS 的加密与认证过程

← TCP 怎么保证可靠传输 简述 HTTPS 的加密与认证过程→

最近更新
01
电商-商品系统设计
12-17
02
关于如何写OKR
12-09
03
对事不对人 vs 对人不对事
12-09
更多文章>
Theme by Vdoing | Copyright © 2022-2023 YoungAnnn | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式