TCP 传输控制协议
传输控制协议 TCP(Transmission Control Protocol)
使用 TCP 协议的通信双方,在进行数据传输之前,必须使用“三报文握手”建立 TCP 连接

TCP 连接建立成功后,通信双方之间就好像有一条可靠的通信信道,通信双方使用这条基于 TCP 连接的可靠信道进行通信

很显然,TCP 仅支持单播,也就是一对一的通信
运输过程

发送方
TCP 会把应用进程交付下来的数据块看作是一连串无结构的字节流,TCP 并不知道这些待传送的字节流的含义
并将他们编号,并存储在自己发送缓存中
TCP 会根据发送策略,提取一定量的字节构建 TCP 报文并发送
接收方
- 一方面从所接受到的 TCP 报文段中,取出数据载荷部分并存储在接收缓存中;一方面将接收缓存中的一些字节交付给应用进程
- TCP 不保证接收方应用进程所收到的数据块与发送方发送的数据块,具有对应大小的关系(例如,发送方应用进程交给发送方的 TCP 共 10 个数据块,但接收方的 TCP 可能只用了 4 个数据块,就把收到的字节流交付给了上层的应用进程,但接收方收到的字节流必须和发送方应用进程发出的字节流完全一样)
- 接收方的应用进程必须有能力识别收到的字节流,把它还原成有意义的应用层数据
TCP 是面向字节流的,这正是 TCP 实现可靠传输、流量控制、以及拥塞控制的基础
本图只画了一个方向的数据流,在实际网络中,基于 TCP 连接的两端,可以同时进行 TCP 报文段的发送和接收
TCP 向上层提供面向连接的可靠传输服务

TCP 结构

1. TCP 首部格式
TCP 首部由固定的 20 字节和可变长度的选项字段组成,首部长度最大可达 60 字节,主要字段如下:
- 源端口(16 位)和目的端口(16 位):标识通信双方的应用进程接口。
- 序号(32 位):标识本报文段中第一个数据字节的序号,用于数据排序和确认。
- 确认号(32 位):期望收到对方下一个字节的序号,仅当 ACK 标志位为 1 时有效。
- 数据偏移(4 位):指明 TCP 首部长度,单位为 4 字节。
- 保留(6 位):暂未使用,置 0。
- 标志位(6 位):
- URG(紧急指针有效)
- ACK(确认号有效)
- PSH(推送功能)
- RST(复位连接)
- SYN(同步序号,用于连接建立)
- FIN(结束连接)
- 窗口大小(16 位):接收方的接收窗口大小,用于流量控制。
- 校验和(16 位):覆盖 TCP 首部和数据,保证数据完整性。
- 紧急指针(16 位):指示紧急数据的字节数。
- 选项和填充(可变长度):如最大报文段长度(MSS)、窗口扩大、时间戳、选择确认(SACK)等。
TCP 首部的结构支持连接管理、数据传输控制和错误检测等功能。
2. 流量控制
流量控制是为了防止发送方发送数据过快,导致接收方缓存溢出和数据丢失。TCP 通过滑动窗口机制实现流量控制:
- 接收方在确认报文中告知发送方当前接收窗口大小(剩余缓存空间)。
- 发送方根据接收窗口调整自己的发送窗口大小,限制未确认数据的发送量。
- 当接收窗口为 0 时,发送方停止发送,并启动定时器,周期性发送探测报文询问接收方窗口是否开放,避免死锁。
- 接收窗口大小动态调整,既不能过小浪费带宽,也不能过大浪费内存,需根据网络和接收方处理能力动态变化。
流量控制保证了端到端的传输平衡,避免接收方缓存溢出。
3. 拥塞控制
拥塞控制是为了防止网络中路由器或链路因数据过多而拥塞,导致丢包和延迟。TCP 拥塞控制主要维护一个拥塞窗口(cwnd),限制发送方的发送速率,包含以下关键算法:
- 慢启动:连接开始时,cwnd 从 1 个 MSS 开始,每收到一个确认,cwnd 加倍增长,快速探测网络容量。
- 拥塞避免:当 cwnd 超过阈值 ssthresh 后,cwnd 线性增长,防止过快增长导致拥塞。
- 快速重传:收到 3 个重复确认时,立即重传丢失的数据包,避免等待超时。
- 快速恢复:在快速重传后,将 cwnd 设为 ssthresh 的一半,避免进入慢启动,缓慢恢复发送速率。
拥塞控制是一个全局问题,动态调节发送速率以适应网络状态,减少拥塞发生。
4. 超时重传时间选择
超时重传时间(RTO)是 TCP 重传机制的核心,选择合理的 RTO 能提高传输效率:
- RTO 应略大于当前的往返时间(RTT),防止不必要的重传。
- 由于网络延迟波动,TCP 采用加权平均算法计算平滑的 RTT 估计(RTTS),并基于 RTTS 和 RTT 偏差计算 RTO。
- 当发生超时重传时,RTO 通常加倍(指数退避),避免网络拥塞加剧。
- 通过动态调整 RTO,TCP 能适应不同网络环境,保证重传及时且不过于频繁。
5. 可靠传输实现
TCP 通过以下机制保证数据可靠传输:
- 序列号:为每个字节编号,保证数据有序且无重复。
- 确认应答(ACK):接收方确认已收到的数据,发送方根据 ACK 调整发送窗口。
- 超时重传:发送方启动定时器,超时未收到确认则重传数据。
- 校验和:检测数据在传输中是否损坏,错误数据被丢弃。
- 流量控制和拥塞控制:防止丢包和网络拥塞,提高传输效率。
- 连接管理:通过三次握手和四次挥手确保连接的正确建立和释放。
这些机制协同工作,确保 TCP 在复杂网络环境中实现可靠传输。
6. 连接管理
TCP 连接管理分为连接建立和连接释放两个阶段:
6.1 连接建立(三次握手)
- 客户端发送 SYN 报文(SYN=1,Seq=x),请求建立连接。
- 服务器响应 SYN+ACK 报文(SYN=1,ACK=1,确认号=x+1,Seq=y),同意连接。
- 客户端发送 ACK 报文(ACK=1,确认号=y+1,Seq=x+1),连接建立完成。
三次握手确保双方都准备好通信,防止旧连接请求误连接。

6.2 连接释放(四次挥手)
- 主动关闭方发送 FIN 报文,表示数据发送完毕。
- 被动关闭方确认 ACK,进入 CLOSE-WAIT 状态,继续发送剩余数据。
- 被动关闭方发送 FIN 报文,表示数据发送完毕。
- 主动关闭方确认 ACK,进入 TIME-WAIT 状态,等待 2 倍最大报文存活时间(2MSL)后关闭连接。
四次挥手保证双方都能完整发送和接收数据,防止数据丢失。
最大报文段长度
1. MSS(最大报文段长度)规定
- 定义:MSS(Maximum Segment Size)是 TCP 报文段中数据部分的最大长度,不包括 TCP 首部。
- 协商机制:
- 在 TCP 三次握手时,双方通过选项字段交换 MSS 值(SYN 报文中携带)。
- 默认值为 536 字节(IPv4)或 1220 字节(IPv6),但实际值由双方根据网络 MTU 动态协商。
- MTU 关联:
- MSS = MTU(链路层最大传输单元) - IP 首部(20 字节) - TCP 首部(20 字节)。
- 例如:以太网 MTU 为 1500 字节时,MSS 通常为 1460 字节(1500 - 20 - 20)。
- 作用:避免 IP 层分片,提高传输效率(IP 分片会降低性能且增加丢包风险)。
2. TCP 数据分片机制
- 分片触发条件:
- 应用层数据超过 MSS 时,TCP 会在发送缓存中将其分割为多个≤MSS 的报文段。
- 每个报文段包含独立的 TCP 首部(序号、确认号等字段)。
- 分片流程:
- 发送方:
- 从发送缓存中读取字节流,按 MSS 切分数据块。
- 为每个数据块添加 TCP 首部(包括序号、标志位等),形成 TCP 报文段。
- 通过滑动窗口控制发送速率。
- 接收方:
- 根据序号重组报文段,确保数据有序且无缺失。
- 通过确认号(ACK)通知发送方已成功接收的数据。
- 发送方:
- 特点:
- 面向字节流:TCP 仅处理字节编号,不关心应用层数据块边界。
- 可靠性保障:通过序号、确认、重传等机制确保分片数据完整到达。
3. 关键对比:MSS vs. MTU
| 特性 | MSS | MTU |
|---|---|---|
| 所属层 | 传输层(TCP) | 网络层(IP) |
| 作用对象 | TCP 数据部分 | 整个 IP 数据包(含 IP 首部) |
| 典型值 | 1460 字节(以太网) | 1500 字节(以太网) |
| 分片触发 | 由 TCP 自动处理 | 由 IP 层处理(需避免) |