# 5.3 TCP协议 ## 一、TCP概述 ### 1.1 什么是TCP **TCP(Transmission Control Protocol)**: - 传输控制协议 - 面向连接的、可靠的传输层协议 - 提供字节流服务 ### 1.2 TCP的特点 - **面向连接**:通信前需要建立连接 - **可靠传输**:保证数据无差错、无丢失、无重复、按序到达 - **字节流**:不保留报文边界 - **全双工**:通信双方可以同时发送和接收 - **流量控制**:防止发送方发送过快 - **拥塞控制**:防止网络过载 ### 1.3 TCP的应用场景 - **HTTP/HTTPS**:网页浏览 - **FTP**:文件传输 - **SMTP/POP3/IMAP**:电子邮件 - **Telnet/SSH**:远程登录 - **数据库访问**:MySQL、Oracle等 --- ## 二、TCP首部格式 ### 2.1 TCP首部结构 ``` 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` ### 2.2 TCP首部字段 **源端口(Source Port,16位)**: - 发送方的端口号 **目的端口(Destination Port,16位)**: - 接收方的端口号 **序号(Sequence Number,32位)**: - 本报文段发送的数据的第一个字节的序号 - 用于数据排序和确认 **确认号(Acknowledgment Number,32位)**: - 期望收到对方下一个报文段的第一个字节的序号 - 表示该序号之前的所有数据都已正确接收 **数据偏移(Data Offset,4位)**: - TCP首部长度,单位为4字节 - 最小值:5(20字节) - 最大值:15(60字节) **保留(Reserved,6位)**: - 保留为将来使用 - 置为0 **控制位(Flags,6位)**: - **URG(Urgent)**:紧急指针有效 - **ACK(Acknowledgment)**:确认号有效 - **PSH(Push)**:推送数据 - **RST(Reset)**:重置连接 - **SYN(Synchronize)**:同步序号,用于建立连接 - **FIN(Finish)**:终止连接 **窗口(Window,16位)**: - 接收方允许发送方发送的数据量 - 用于流量控制 - 单位:字节 **校验和(Checksum,16位)**: - 检测TCP首部和数据的错误 - 计算时包括伪首部 **紧急指针(Urgent Pointer,16位)**: - 紧急数据的最后一个字节的序号 - URG=1时有效 **选项(Options,可变)**: - 最大报文段长度(MSS) - 窗口扩大选项 - 时间戳选项 - 选择性确认(SACK) **填充(Padding)**: - 使首部长度为4字节的整数倍 --- ## 三、TCP连接管理 ### 3.1 TCP连接建立(三次握手) **过程**: ``` 客户端 服务器 | | |-------- SYN, seq=x --->| | | |<-- SYN, ACK, seq=y, ack=x+1 --| | | |-------- ACK, ack=y+1 -->| | | ``` **第一次握手**: - 客户端发送SYN报文段 - SYN=1,seq=x(初始序号) - 客户端进入SYN_SENT状态 **第二次握手**: - 服务器发送SYN+ACK报文段 - SYN=1,ACK=1,seq=y(初始序号),ack=x+1 - 服务器进入SYN_RCVD状态 **第三次握手**: - 客户端发送ACK报文段 - ACK=1,ack=y+1 - 客户端和服务器都进入ESTABLISHED状态 **为什么是三次握手**: - 防止历史连接初始化 - 同步双方初始序号 - 确认双方收发能力正常 ### 3.2 TCP连接释放(四次挥手) **过程**: ``` 客户端 服务器 | | |-------- FIN, seq=u --->| | | |<-------- ACK, ack=u+1 --| | | |<-------- FIN, seq=w ----| | | |-------- ACK, ack=w+1 -->| | | ``` **第一次挥手**: - 客户端发送FIN报文段 - FIN=1,seq=u - 客户端进入FIN_WAIT_1状态 **第二次挥手**: - 服务器发送ACK报文段 - ACK=1,ack=u+1 - 服务器进入CLOSE_WAIT状态 - 客户端进入FIN_WAIT_2状态 **第三次挥手**: - 服务器发送FIN报文段 - FIN=1,seq=w - 服务器进入LAST_ACK状态 **第四次挥手**: - 客户端发送ACK报文段 - ACK=1,ack=w+1 - 客户端进入TIME_WAIT状态 - 服务器进入CLOSED状态 - 客户端等待2MSL后进入CLOSED状态 **TIME_WAIT状态**: - 等待2MSL(Maximum Segment Lifetime) - 确保最后一个ACK到达 - 防止旧连接的数据包干扰新连接 **为什么是四次挥手**: - TCP是全双工通信 - 每个方向需要单独关闭 - 一方发送FIN后,另一方可能还有数据要发送 ### 3.3 TCP状态转换 **客户端状态转换**: ``` CLOSED -> SYN_SENT -> ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED ↓ CLOSE_WAIT -> LAST_ACK -> CLOSED(服务器) ``` **服务器状态转换**: ``` CLOSED -> LISTEN -> SYN_RCVD -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED ``` --- ## 四、TCP可靠传输 ### 4.1 序号和确认机制 **序号**: - 每个字节都有序号 - 报文段的序号是该报文段第一个字节的序号 **确认**: - 累积确认 - 确认号表示期望收到的下一个字节的序号 - 表示该序号之前的所有数据都已正确接收 ### 4.2 超时重传 **超时时间**: - 根据往返时间(RTT)动态计算 - 加权平均:RTTₛ = (1-α)×RTTₛ + α×RTT样本 - 超时时间:RTO = RTTₛ + 4×RTTd **重传**: - 超时未收到确认,重传该报文段 - 重传后超时时间加倍 ### 4.3 快速重传 **机制**: - 收到3个重复ACK,立即重传 - 不需要等待超时 **过程**: 1. 发送方发送报文段1、2、3、4、5 2. 报文段2丢失 3. 接收方收到1、3、4、5 4. 接收方对1重复发送ACK(确认号=2) 5. 收到3个重复ACK后,发送方重传2 ### 4.4 选择性确认(SACK) **机制**: - 接收方告诉发送方已收到的不连续的数据块 - 发送方只重传丢失的数据 **选项**: - TCP选项中的SACK选项 - 最多报告4个数据块 --- ## 五、TCP流量控制 ### 5.1 什么是流量控制 **流量控制**: - 控制发送方的发送速率 - 防止接收方缓冲区溢出 - 端到端的控制 ### 5.2 滑动窗口机制 **接收窗口(rwnd)**: - 接收方告诉发送方自己的接收缓冲区大小 - 发送方发送的数据量不能超过rwnd **发送窗口**: - 发送方可以发送的数据量 - 受rwnd和拥塞窗口cwnd的限制 - 发送窗口 = min(rwnd, cwnd) ### 5.3 窗口调整 **接收方**: - 根据缓冲区剩余空间调整rwnd - 在ACK报文中通告rwnd **发送方**: - 根据rwnd调整发送窗口 - 如果rwnd=0,停止发送 - 启动持续计时器,定期探测窗口大小 ### 5.4 零窗口问题 **问题**: - rwnd=0,发送方停止发送 - 接收方恢复后发送的窗口更新报文丢失 - 双方死锁 **解决**: - 持续计时器(Persistence Timer) - 超时后发送窗口探测报文 --- ## 六、TCP拥塞控制 ### 6.1 什么是拥塞控制 **拥塞**: - 网络中分组过多 - 路由器缓冲区溢出 - 延迟增加、丢包 **拥塞控制**: - 防止网络过载 - 全局性的控制 - 与流量控制的区别: - 流量控制:端到端,防止接收方溢出 - 拥塞控制:全局,防止网络过载 ### 6.2 拥塞窗口(cwnd) **cwnd**: - 发送方根据网络拥塞程度调整的窗口 - 限制发送方的发送速率 - 发送窗口 = min(rwnd, cwnd) ### 6.3 拥塞控制算法 #### 慢开始(Slow Start) **机制**: - 初始cwnd = 1 MSS - 每收到一个ACK,cwnd增加1 MSS - 每经过一个RTT,cwnd翻倍 - 指数增长 **阈值(ssthresh)**: - 慢开始阈值 - cwnd < ssthresh:慢开始 - cwnd ≥ ssthresh:拥塞避免 #### 拥塞避免(Congestion Avoidance) **机制**: - cwnd ≥ ssthresh时 - 每收到一个ACK,cwnd增加1/cwnd - 每经过一个RTT,cwnd增加1 MSS - 线性增长 #### 快重传(Fast Retransmit) **机制**: - 收到3个重复ACK,立即重传 - 不等待超时 #### 快恢复(Fast Recovery) **机制**: - 收到3个重复ACK后 - ssthresh = cwnd / 2 - cwnd = ssthresh + 3 MSS - 进入拥塞避免(不是慢开始) ### 6.4 拥塞控制过程 ``` cwnd │ │ ╱╲ │ ╱ ╲ │ ╱ ╲____ │ ╱ ╲___ │╱ ╲___ └─────────────────────────> 时间 慢开始 拥塞避免 快恢复 ``` **过程**: 1. 初始:cwnd=1,慢开始 2. cwnd指数增长,直到ssthresh 3. 进入拥塞避免,cwnd线性增长 4. 超时:ssthresh=cwnd/2,cwnd=1,慢开始 5. 或3个重复ACK:ssthresh=cwnd/2,cwnd=ssthresh+3,快恢复 ### 6.5 TCP拥塞控制版本 **TCP Tahoe**: - 慢开始 + 拥塞避免 - 超时后cwnd=1 **TCP Reno**: - 增加快重传和快恢复 - 3个重复ACK后快恢复 **TCP NewReno**: - 改进快恢复 - 部分ACK也触发快恢复 **TCP Vegas**: - 基于延迟的拥塞控制 - 预测拥塞,提前调整 **TCP CUBIC**: - Linux默认 - 使用三次函数调整cwnd - 适合高带宽延迟积网络 --- ## 七、TCP与UDP的比较 | 特性 | TCP | UDP | |-----|-----|-----| | 连接 | 面向连接 | 无连接 | | 可靠性 | 可靠 | 不可靠 | | 有序性 | 有序 | 无序 | | 流量控制 | 有 | 无 | | 拥塞控制 | 有 | 无 | | 首部大小 | 20-60字节 | 8字节 | | 传输效率 | 较低 | 高 | | 延迟 | 较大 | 小 | | 应用场景 | 文件传输、网页 | 实时应用、DNS | --- ## 八、考研重点 1. **TCP的特点**: - 面向连接 - 可靠传输 - 字节流 - 全双工 2. **TCP首部格式**: - 各字段的含义 - 序号、确认号 - 控制位(SYN、ACK、FIN等) - 窗口、校验和 3. **TCP连接管理**: - 三次握手:过程、为什么是三次 - 四次挥手:过程、为什么是四次 - TIME_WAIT状态 - 状态转换 4. **TCP可靠传输**: - 序号和确认机制 - 超时重传 - 快速重传 - 选择性确认(SACK) 5. **TCP流量控制**: - 滑动窗口机制 - 接收窗口rwnd - 零窗口问题 6. **TCP拥塞控制**: - 拥塞窗口cwnd - 慢开始 - 拥塞避免 - 快重传 - 快恢复 - 拥塞控制过程 7. **TCP与UDP的比较** --- *下一节:5.4 TCP可靠传输*