第3章 第15.1天
TCP协议:可靠传输的工程艺术
大家好,今天我们来拆解互联网的"可靠信使"——TCP协议。从你登录教务系统到实验室服务器传输数据,背后都是它在默默守护。我会用学生选课系统、实验室文件传输这些真实场景,带你理解TCP如何确保数据可靠到达。
一、TCP核心特性:连接与可靠的基石
协议定位:面向连接的、可靠的字节流传输协议
设计哲学:在不可靠的IP层之上构建可靠通道
典型场景:
- 网页浏览(HTTP/HTTPS)
- 文件传输(FTP/SFTP)
- 远程登录(SSH)
// TCP状态变迁简图(关键节点)
CLOSED → SYN_SENT → ESTABLISHED → FIN_WAIT_1 → TIME_WAIT → CLOSED
三次握手建立四次挥手关闭
二、连接管理:三次握手与四次挥手
三次握手(建立连接):
- 客户端 → SYN=1, Seq=x
"你好,我想建立连接"(SYN_SENT) - 服务器 → SYN=1, ACK=1, Seq=y, Ack=x+1
"收到,我同意连接"(SYN_RCVD) - 客户端 → ACK=1, Seq=x+1, Ack=y+1
"确认收到"(ESTABLISHED)
# Python模拟三次握手(伪代码)
def three_way_handshake():
# 客户端发送SYN
packet1 = TCPHeader(flags=['SYN'], seq=random.randint(0,2**32))
send_to_server(packet1)
# 服务器响应SYN+ACK
packet2 = TCPHeader(flags=['SYN','ACK'], seq=random.randint(0,2**32), ack=packet1.seq+1)
send_to_client(packet2)
# 客户端确认ACK
packet3 = TCPHeader(flags=['ACK'], seq=packet1.seq+1, ack=packet2.seq+1)
send_to_server(packet3)
四次挥手(断开连接):
- 主动方 → FIN=1, Seq=u
"我要关闭连接了"(FIN_WAIT_1) - 被动方 → ACK=1, Seq=v, Ack=u+1
"收到关闭请求"(CLOSE_WAIT) - 被动方 → FIN=1, Seq=w, Ack=u+1
"我也准备关闭"(LAST_ACK) - 主动方 → ACK=1, Seq=u+1, Ack=w+1
"确认关闭"(TIME_WAIT → CLOSED)
三、可靠传输机制:数据不丢失的秘密
- 序列号与确认号
- 每个字节分配唯一序号(Seq)
- 确认号(Ack)= 期望接收的下一个字节序号
# Wireshark抓包示例
Seq=1 Len=1460 Ack=1# 发送1460字节从1开始
Seq=1461 Len=1460 Ack=1 # 继续发送1460字节
Ack=2921 Win=501# 接收方确认收到前2920字节
- 超时重传
- RTT(往返时间)动态计算
- 重传超时(RTO) = RTT + 4*RTT_var
// Linux内核估算RTO(简化)
delta = current_rtt - srtt;
srtt = srtt + delta/8;// 平滑RTT
rttvar = rttvar + |delta|/4;
rto = srtt + max(1, 4*rttvar);
- 滑动窗口
- 接收窗口(rwnd):接收方缓冲区大小
- 拥塞窗口(cwnd):网络承载能力
- 实际窗口 = min(rwnd, cwnd)
四、流量控制与拥塞控制
- 流量控制(接收方主导)
- 通过Window字段通告剩余缓冲区
- 零窗口探测(ZWP):防止窗口更新丢失
- 拥塞控制(网络状态主导)
- 慢启动:指数增长cwnd(1→2→4→8...)
- 拥塞避免:cwnd > ssthresh时线性增长
- 快重传:收到3个重复ACK立即重传
- 快恢复:重传后不回归慢启动
graph LR
A[慢启动 cwnd=1] -->|到达ssthresh| B[拥塞避免]
B -->|丢包| C[快重传/快恢复]
C --> B
五、TCP报文结构详解
// TCP头部结构(20字节基础+选项)
// ----------------------------------------------------
// | Source Port (16bit) | Dest Port (16bit)|
// | Sequence Number (32bit)|
// | Acknowledgment Number (32bit)|
// | Data Offset|Resv | Flags (6bit) | Window (16bit) |
// | Checksum (16bit)| Urgent Pointer (16bit)|
// | Options (可变长度)|
// ----------------------------------------------------
关键字段:
- Flags位:URG/ACK/PSH/RST/SYN/FIN(控制连接状态)
- Window:流量控制窗口大小(2^16=65535字节)
- Options:支持扩展功能(MSS、SACK、时间戳等)
六、Wireshark实战分析
实验准备:
- 浏览器访问 http://www.pinginglab.net
- Telnet连接公共路由服务器:
telnet route-server.ip.att.net
过滤技巧:
# 分析HTTP连接
tcp.port == 80 && ip.addr == <服务器IP>
# 分析Telnet连接
tcp.port == 23 && tcp.flags.syn == 1
关键分析点:
- 三次握手:SYN → SYN+ACK → ACK序列
- 数据传输:Seq/Ack号的变化规律
- 滑动窗口:Window字段值的变化
- 四次挥手:FIN/ACK交换过程
- 特殊标志:PSH标志(催促接收方立即处理)
七、TCP性能优化实践
- TIMEWAIT优化(服务器端)
# Linux内核调整
sysctl -w net.ipv4.tcp_tw_reuse=1# 重用TIME_WAIT连接
sysctl -w net.ipv4.tcp_tw_recycle=1 # 快速回收
- 拥塞算法选择
# 查看可用算法
sysctl net.ipv4.tcp_available_congestion_control
# cubic reno bbr
# 启用BBR算法
sysctl -w net.ipv4.tcp_congestion_control=bbr
- 缓冲区调整
# 增加接收缓冲区
sysctl -w net.core.rmem_max=16777216
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
总结:TCP的设计智慧
- 可靠优先:确认重传机制确保数据完整
- 动态适应:拥塞控制感知网络状态
- 连接导向:状态机管理会话生命周期
- 灵活扩展:Option字段支持未来演进
动手实验建议:
- 用Wireshark抓取微信文件传输的TCP流
- 对比不同拥塞控制算法(cubic/bbr)的传输速度
- 编写简易TCP服务端/客户端(Python socket)
理解TCP不仅是网络基础,更是构建可靠系统的必修课。它教会我们:在不可靠的世界里,用严谨的协议守护每一次数据传输。
感谢浏览和学习,作者:鱼油YOU,转载请注明原文链接:https://www.cnblogs.com/OmegaYOU3/p/19020802,或者可以➕主播WX:OmegaAnimeman_desu;QQ:3819054512
浙公网安备 33010602011771号