mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
455 字
1 分钟
为什么 TCP/IP 协议会拆分数据
2023-05-26

当你通过 TCP 发送一个大的数据包时,它会被拆分传递到接收端。这是为什么?本文深入解析 TCP/IP 协议数据拆分的设计原理。

一、从应用到网络的数据旅程#

1.1 数据封装过程#

flowchart TB subgraph 应用层 A[应用数据<br/>如 HTTP 请求] end subgraph 传输层 T[TCP 头 + 数据] end subgraph 网络层 I[IP 头 + TCP 数据] end subgraph 数据链路层 D[以太网帧<br/>Ethernet Header + IP 数据 + CRC] end A --> T T --> I I --> D

1.2 MTU 的限制#

MTU(Maximum Transmission Unit) 是数据链路层能够传输的最大数据单元:

网络类型MTU
以太网1500 字节
FDDI4352 字节
PPPoE1492 字节
Loopback65535 字节

二、IP 协议的分片机制#

2.1 IP 分片原理#

当 IP 包大小超过 MTU 时,IP 协议会对数据进行分片:

flowchart LR subgraph 原始 IP 包 H[IP Header] D[Data: 3000 字节] end subgraph 分片 1 H1[IP Header<br/>MF=1, Offset=0] D1[Data: 0-1399] end subgraph 分片 2 H2[IP Header<br/>MF=1, Offset=1400] D2[Data: 1400-2799] end subgraph 分片 3 H3[IP Header<br/>MF=0, Offset=2800] D3[Data: 2800-2999] end D --> H1 D --> H2 D --> H3

2.2 IP 分片字段#

字段说明
Identification同一包的所有分片共享相同 ID
FlagsMF(更多分片)=1 表示还有后续分片
Fragment Offset分片在原始数据中的偏移量

2.3 分片重组#

sequenceDiagram participant S as 发送方 participant R as 接收方 participant N as 网络(可能分片) S->>N: 发送大数据包 N->>R: 分片 1 (MF=1) N->>R: 分片 2 (MF=1) N->>R: 分片 3 (MF=0) Note over R: 等待所有分片<br/>按偏移重组

问题:如果任何一个分片丢失,整个 IP 包都需要重传。

三、TCP 的 MSS 机制#

3.1 什么是 MSS?#

MSS(Maximum Segment Size) 是 TCP 层能够传输的最大数据量:

# MSS 计算
MSS = MTU - IP头(20字节) - TCP头(20字节)
MSS = 1500 - 20 - 20 = 1460 字节

3.2 MSS 协商#

sequenceDiagram participant C as 客户端 participant S as 服务端 C->>S: SYN (MSS=1460) S->>C: SYN+ACK (MSS=1460) Note over C,S: 双方使用较小的 MSS

四、粘包问题#

4.1 什么是粘包?#

TCP 是字节流协议,不保留消息边界:

flowchart LR subgraph 发送 M1[消息 A: 100B] M2[消息 B: 50B] M3[消息 C: 80B] end subgraph TCP 字节流 B[100B | 50B | 80B] end subgraph 接收(可能) R1[消息 A: 100B] R2[消息 B: 50B] R3[消息 C: 80B] end M1 --> B M2 --> B M3 --> B B --> R1 B --> R2 B --> R3

4.2 粘包的原因#

原因说明
Nagle 算法合并小数据包以减少网络开销
滑动窗口多个数据包可能在网络中同时传输
接收缓冲区数据可能在缓冲区中合并

4.3 解决方案#

# 方案 1:固定长度
data = sock.recv(1024) # 每次读取固定长度
# 方案 2:分隔符
data = sock.recv_until(b'\n') # 读取到换行符
# 方案 3:长度前缀
# 先读取 4 字节长度,再读取对应长度数据
length = struct.unpack('!I', sock.recv(4))[0]
data = sock.recv(length)

五、总结#

层级拆分机制问题
IP分片分片丢失需重传整个包
TCPMSS 限制字节流,无消息边界
应用层需自定义协议粘包问题

理解 TCP/IP 的数据拆分机制,是设计高性能网络应用的基础。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

为什么 TCP/IP 协议会拆分数据
https://blog.souloss.com/posts/why-the-design/why-tcp-ip-splits-data/
作者
Souloss
发布于
2023-05-26
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时