TCP 协议
- [TCP 报头结构](#TCP 报头结构)
-
- 各字段详细说明
- [9 个标志位详解](#9 个标志位详解)
- 可靠传输
- 连接管理
- 面向字节流
- 滑动窗口
- 流量控制和拥塞控制
- 延时应答
- 异常情况处理
- [TCP 与 UDP 全面对比表⭐](#TCP 与 UDP 全面对比表⭐)
- [如何基于 UDP 实现可靠传输⭐](#如何基于 UDP 实现可靠传输⭐)
-
- [1. 分包与组包](#1. 分包与组包)
- [2. 确认应答(ACK)](#2. 确认应答(ACK))
- [3. 超时重传](#3. 超时重传)
- [4. 乱序与去重处理](#4. 乱序与去重处理)
- [5. 流量控制](#5. 流量控制)
- [6. 拥塞控制](#6. 拥塞控制)
- [7. 连接管理](#7. 连接管理)
TCP 报头结构
TCP 报头最小为 20 字节,最多可扩展至 60 字节,比 UDP 复杂得多,因为需要支持可靠性、流量控制、拥塞控制等机制。
至少20字节
源端口号
2字节
目的端口号
2字节
序列号
4字节
确认序列号
4字节
数据偏移+保留+标志位
2字节
窗口大小
2字节
校验和
2字节
紧急指针
2字节
选项字段
可选
应用层数据
各字段详细说明
| 字段 | 大小 | 说明 |
|---|---|---|
| 源端口号 | 2 字节 | 发送方端口号 |
| 目的端口号 | 2 字节 | 接收方端口号 |
| 序号 | 4 字节 | 本报文段数据的第一个字节的编号 |
| 确认号 | 4 字节 | 期望收到对方下一个报文段的第一个字节序号 |
| 数据偏移 | 4 位 | TCP 报头长度 / 4(即有多少个 4 字节) |
| 保留 | 3 位 | 全 0,保留未来用 |
| 标志位 | 9 位 | 控制连接状态(见下表) |
| 窗口大小 | 2 字节 | 接收方还能接收多少字节(流量控制) |
| 校验和 | 2 字节 | 检验报头 + 数据是否损坏 |
| 紧急指针 | 2 字节 | URG=1 时有效,指明紧急数据末尾位置 |
| 可选项 | 0~40 字节 | MSS、窗口缩放、时间戳等扩展功能 |
UDP 报头固定 8 字节,而 TCP 报头最小 20 字节,开销更大但功能更强。
9 个标志位详解
9 个标志位(9 bit)
NS
CWR
ECE
URG
ACK
PSH
RST
SYN
FIN
| 标志位 | 全称 | 作用 |
|---|---|---|
| NS | Nonce Sum | ECN 防伪,极少使用 |
| CWR | Congestion Window Reduced | 发送方告知"我已减小拥塞窗口" |
| ECE | ECN-Echo | 通知对方"我遇到了网络拥塞" |
| URG | Urgent | 紧急指针有效,数据需优先处理 |
| ACK | Acknowledgment | 确认号字段有效(连接建立后始终置 1) |
| PSH | Push | 催促接收方立即提交应用层,不缓存 |
| RST | Reset | 强制重置连接(异常终止) |
| SYN | Synchronize | 建立连接(三次握手的开始) |
| FIN | Finish | 释放连接(四次挥手的开始) |
实际抓包中最常见的是:SYN、ACK、FIN、RST、PSH 五个。
可靠传输
连接管理
面向字节流
滑动窗口
流量控制和拥塞控制
延时应答
异常情况处理
TCP 与 UDP 全面对比表⭐
| 特性 | TCP | UDP |
|---|---|---|
| 连接模型 | 面向连接,需三次握手建立连接 | 无连接,直接发送数据 |
| 数据顺序 | 序列号保证,接收顺序与发送一致 | 无序,可能后发先至 |
| 可靠性 | 确认应答 + 超时重传 + 快速重传,保证数据到达 | 无确认,丢包即丢失,不重传 |
| 重复数据 | 接收缓冲区自动去重 | 可能重复,需应用层自行去重 |
| 流量控制 | 滑动窗口机制,防止发送方淹没接收方 | 无,可能丢包或接收方缓冲区溢出 |
| 拥塞控制 | 有多种拥塞控制算法(慢启动、拥塞避免、快速恢复等) | 无,可能加剧网络拥塞 |
| 大包传输 | 自动分段,应用层无需关心 | 需应用层手动分包/组包(受 MTU 限制) |
| 头部开销 | 最小 20 字节 | 固定 8 字节 |
| 端口 | 0~65535,服务器常用固定端口,客户端自动分配 | 同 TCP |
| 校验和 | 强制校验(IPv4 可选项,但通常使用),更严格 | 可选校验,主要用于防比特翻转 |
| 编程复杂度 | 提供可靠字节流,编程简单,只需读写 | 若需可靠传输,必须自行实现拆包、组包、排序、确认、重传、去重、流量控制等 |
| 典型场景 | 文件传输、网页浏览、邮件等要求数据完整和顺序的场景 | 视频直播、语音通话、DNS 查询、局域网简单请求-响应等容忍少量丢包、追求低延迟的场景 |
如何基于 UDP 实现可靠传输⭐
UDP 本身只提供最基础的"端口到端口"数据报发送,不保证可靠性。要基于 UDP 实现可靠传输,必须在应用层补充以下机制:
1. 分包与组包
- UDP 数据报大小受路径 MTU 限制,对于大块数据需要应用层负责拆分,并为每个分片添加序号 和分片标识(如首片、中间片、尾片)。
- 接收方按序号重组,确认所有分片到齐后再交付上层。
2. 确认应答(ACK)
- 发送方为每个数据包或每组分片分配唯一序号。
- 接收方收到数据后,回复 ACK 报文,携带已成功接收的最大连续序号或位图(SACK,选择性确认),以通知发送方哪些包已到达。
- 发送方根据 ACK 判断是否需要重传。
3. 超时重传
- 发送方在发送数据后启动定时器,若超时未收到对应 ACK,则重传该数据包。
- 超时时间(RTO)需要根据网络往返时间(RTT)动态估算,避免过早或过晚重传。
4. 乱序与去重处理
- 接收方根据序号对数据包排序,使交付给上层的数据流保持原始顺序。
- 接收方需维护已接收序号集合,对重复到达的数据包直接丢弃,避免重复递交。
5. 流量控制
- 接收方在 ACK 中通告自身的接收窗口(缓冲区剩余大小),限制发送方在未确认情况下的最大发送量,防止接收方被淹没。
- 发送方根据通告窗口调整发送速率。
6. 拥塞控制
- 实现类似 TCP 的拥塞控制算法(如慢启动、拥塞避免、快速重传与恢复),根据丢包和延迟变化调整发送速率,避免过度占用网络导致拥塞崩溃。
- 典型的基于 UDP 的可靠协议(如 QUIC)都内置了拥塞控制模块。
7. 连接管理
- 虽然 UDP 无连接,但可靠传输通常需要维护会话状态。可通过握手(如 Hello/HelloAck)建立连接,通过关闭消息或超时来拆除连接,以便管理资源、初始化序号等。
综合来看,实现一个完整的可靠 UDP 协议工作量巨大,实际上相当于重新实现一个类 TCP 的传输层,现代做法通常直接采用已成熟的 QUIC 等协议,而不是从零开始。