TCP/IP 协议栈是互联网的基础,理解它对于任何开发者都至关重要。本文将深入剖析 TCP/IP 的核心原理。
TCP/IP 四层模型
┌─────────────────────────────────────┐
│ 应用层 (Application) │ HTTP, FTP, DNS, SMTP
├─────────────────────────────────────┤
│ 传输层 (Transport) │ TCP, UDP
├─────────────────────────────────────┤
│ 网络层 (Internet) │ IP, ICMP, ARP
├─────────────────────────────────────┤
│ 网络接口层 (Link) │ Ethernet, WiFi
└─────────────────────────────────────┘
IP 协议
IP 地址
IPv4 地址: 32位,如 192.168.1.1
IPv6 地址: 128位,如 2001:0db8:85a3:0000:0000:8a2e:0370:7334
特殊地址:
- 127.0.0.1: 本地回环
- 0.0.0.0: 任意地址
- 255.255.255.255: 广播地址
- 10.x.x.x, 172.16-31.x.x, 192.168.x.x: 私有地址
IP 数据包结构
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
路由
路由表示例:
Destination Gateway Genmask Iface
0.0.0.0 192.168.1.1 0.0.0.0 eth0 # 默认路由
192.168.1.0 0.0.0.0 255.255.255.0 eth0 # 本地网络
10.0.0.0 192.168.1.254 255.0.0.0 eth0 # 静态路由
TCP 协议详解
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
三次握手(建立连接)
客户端 服务器
| |
| -------- SYN, seq=x ---------> | 第1次:客户端发送 SYN
| |
| <--- SYN+ACK, seq=y, ack=x+1 --- | 第2次:服务器确认并发送 SYN
| |
| -------- ACK, ack=y+1 --------> | 第3次:客户端确认
| |
| 连接建立 |
为什么需要三次握手?
- 确认双方的发送和接收能力
- 防止历史连接的初始化
- 同步初始序列号
四次挥手(断开连接)
客户端 服务器
| |
| -------- FIN, seq=u ---------> | 第1次:客户端请求断开
| |
| <------- ACK, ack=u+1 -------- | 第2次:服务器确认
| |
| (服务器可能还有数据要发送) |
| |
| <------- FIN, seq=v ---------- | 第3次:服务器请求断开
| |
| -------- ACK, ack=v+1 --------> | 第4次:客户端确认
| |
| TIME_WAIT (2MSL) |
| 连接关闭 |
为什么需要 TIME_WAIT?
- 确保最后的 ACK 能够到达
- 让本连接的重复数据段过期
TCP 状态机
+---------+
| CLOSED |
+---------+
| |
被动打开 | | 主动打开
| v
+---------+
| LISTEN |
+---------+
| |
收到SYN | | 发送SYN
| v
+----------+ +---------+
|SYN_RCVD |<-----------------|SYN_SENT |
+----------+ 收到SYN,发送 +---------+
| SYN+ACK |
| |
| 收到ACK | 收到SYN+ACK
v v
+---------+ +---------+
|ESTABLISH|<----------------->|ESTABLISH|
+---------+ 连接建立 +---------+
可靠传输机制
滑动窗口
发送窗口:
+---+---+---+---+---+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
+---+---+---+---+---+---+---+---+---+---+
已确认 |<-- 发送窗口 -->| 未发送
接收窗口:
+---+---+---+---+---+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
+---+---+---+---+---+---+---+---+---+---+
已接收 |<-- 接收窗口 -->|
流量控制
接收方通过窗口大小字段告知发送方自己的处理能力:
发送方 接收方
| |
| --- 数据 (seq=1, len=1000) ---> |
| |
| <-- ACK=1001, win=2000 --- | "我还能接收 2000 字节"
| |
| --- 数据 (seq=1001, len=2000) -->|
| |
| <-- ACK=3001, win=0 --- | "窗口为0,暂停发送"
| |
| (发送方等待) |
| |
| <-- ACK=3001, win=1000 --- | "窗口更新,可以继续"
拥塞控制
拥塞窗口 (cwnd) 的变化:
cwnd
^
|
ssthresh -------+
| /|\
| / | \
| / | \-- 拥塞发生
| / |
| / |
| / +------ 拥塞避免
| / 慢启动
|/
+---------------> 时间
四种算法
-
慢启动(Slow Start)
- 初始 cwnd = 1 MSS
- 每收到一个 ACK,cwnd 翻倍
- 指数增长直到 ssthresh
-
拥塞避免(Congestion Avoidance)
- cwnd >= ssthresh 时启用
- 每个 RTT,cwnd += 1 MSS
- 线性增长
-
快重传(Fast Retransmit)
- 收到 3 个重复 ACK 立即重传
-
快恢复(Fast Recovery)
- ssthresh = cwnd / 2
- cwnd = ssthresh + 3
- 进入拥塞避免阶段
UDP 协议
UDP vs TCP
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接 | 无连接 |
| 可靠性 | 可靠传输 | 不可靠 |
| 顺序 | 保证顺序 | 不保证 |
| 流量控制 | 有 | 无 |
| 速度 | 较慢 | 较快 |
| 头部开销 | 20+ 字节 | 8 字节 |
| 应用场景 | HTTP, FTP | DNS, 视频流 |
UDP 头部
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source | Destination |
| Port | Port |
+--------+--------+--------+--------+
| Length | Checksum |
+--------+--------+--------+--------+
| data octets ... |
+-----------------------------------+
实用网络命令
# 查看网络接口
ip addr
# 查看路由表
ip route
# 查看 TCP 连接状态
netstat -ant
ss -t
# 抓包分析
tcpdump -i eth0 port 80
tcpdump -i any tcp and port 443 -w capture.pcap
# 测试连通性
ping google.com
traceroute google.com
# DNS 查询
nslookup google.com
dig google.com
常见面试题
1. 为什么 TIME_WAIT 状态需要等待 2MSL?
MSL(Maximum Segment Lifetime)是报文最大生存时间。等待 2MSL 确保:
- 本连接的数据包已经消失
- 最后的 ACK 有机会重传
2. TCP 如何保证可靠传输?
- 序列号和确认号
- 超时重传
- 滑动窗口
- 校验和
- 流量控制
- 拥塞控制
3. SYN 洪泛攻击原理及防御
攻击:发送大量 SYN 包但不回复 ACK,耗尽服务器资源。
防御:
- SYN Cookie
- 限制半连接数量
- 缩短 SYN_RCVD 超时
- 使用防火墙过滤
总结
理解 TCP/IP 协议栈的关键点:
- 分层思想 - 每层只关注自己的职责
- IP 负责寻址 - 找到目标在哪里
- TCP 保证可靠 - 确保数据完整到达
- 三次握手/四次挥手 - 连接管理的核心
- 流量控制/拥塞控制 - 网络效率的保障
掌握这些知识,不仅面试有用,更能帮助你排查网络问题。