TCP/IP 协议栈详解

foxgem

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次:客户端确认
   |                                         |
   |            连接建立                      |

为什么需要三次握手?

  1. 确认双方的发送和接收能力
  2. 防止历史连接的初始化
  3. 同步初始序列号

四次挥手(断开连接)

客户端                                    服务器
   |                                         |
   |  -------- FIN, seq=u --------->        |  第1次:客户端请求断开
   |                                         |
   |  <------- ACK, ack=u+1 --------        |  第2次:服务器确认
   |                                         |
   |       (服务器可能还有数据要发送)          |
   |                                         |
   |  <------- FIN, seq=v ----------        |  第3次:服务器请求断开
   |                                         |
   |  -------- ACK, ack=v+1 -------->       |  第4次:客户端确认
   |                                         |
   |         TIME_WAIT (2MSL)                |
   |            连接关闭                      |

为什么需要 TIME_WAIT?

  1. 确保最后的 ACK 能够到达
  2. 让本连接的重复数据段过期

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 -------+
          |       /|\
          |      / | \
          |     /  |  \-- 拥塞发生
          |    /   |
          |   /    |
          |  /     +------ 拥塞避免
          | / 慢启动
          |/
          +---------------> 时间

四种算法

  1. 慢启动(Slow Start)

    • 初始 cwnd = 1 MSS
    • 每收到一个 ACK,cwnd 翻倍
    • 指数增长直到 ssthresh
  2. 拥塞避免(Congestion Avoidance)

    • cwnd >= ssthresh 时启用
    • 每个 RTT,cwnd += 1 MSS
    • 线性增长
  3. 快重传(Fast Retransmit)

    • 收到 3 个重复 ACK 立即重传
  4. 快恢复(Fast Recovery)

    • ssthresh = cwnd / 2
    • cwnd = ssthresh + 3
    • 进入拥塞避免阶段

UDP 协议

UDP vs TCP

特性TCPUDP
连接面向连接无连接
可靠性可靠传输不可靠
顺序保证顺序不保证
流量控制
速度较慢较快
头部开销20+ 字节8 字节
应用场景HTTP, FTPDNS, 视频流

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 协议栈的关键点:

  1. 分层思想 - 每层只关注自己的职责
  2. IP 负责寻址 - 找到目标在哪里
  3. TCP 保证可靠 - 确保数据完整到达
  4. 三次握手/四次挥手 - 连接管理的核心
  5. 流量控制/拥塞控制 - 网络效率的保障

掌握这些知识,不仅面试有用,更能帮助你排查网络问题。