每天我们都在和 TCP/IP 打交道:刷网页、看视频、聊微信。但当 HTTP 请求到达服务器时,数据是怎么一层层”剥洋葱”传递的? 本文从最基础的概念讲起,带你穿透协议栈,理解每一次网络通信背后的原理。

一、为什么需要协议

想象一个没有协议的世界:你写的数据,对方根本看不懂。就像两个人说话如果语言不通,只能鸡同鸭讲。

协议就是通信双方约定的规则:

  • 数据格式
  • 传输顺序
  • 错误处理
  • 状态管理

二、网络分层模型

OSI 七层模型(理论)

1
2
3
4
5
6
7
7  应用层     ← HTTP、FTP、DNS、SMTP
6 表示层 ← 数据格式、加密
5 会话层 ← 建立/维护会话
4 传输层 ← TCP、UDP
3 网络层 ← IP、ICMP、ARP
2 数据链路层 ← 以太网、Wi-Fi
1 物理层 ← 网线、光纤、无线电

TCP/IP 四层模型(实际)

1
2
3
4
4  应用层     ← HTTP、DNS、SSH
3 传输层 ← TCP、UDP
2 网络层 ← IP、ICMP
1 网络接口层 ← 以太网、ARP

每层只关心自己的事,通过接口与上下层通信。这种设计的好处是解耦——改一层的实现不影响其他层。

三、数据封装过程(发送方)

1
2
3
4
5
6
7
8
9
应用层:    [HTTP 请求数据]
↓ 加 HTTP 头
传输层: [TCP 头 | HTTP 数据]
↓ 加 TCP 头
网络层: [IP 头 | TCP 头 | HTTP 数据]
↓ 加 IP 头
链路层: [帧头 | IP 头 | TCP 头 | HTTP 数据 | 帧尾]
↓ 加帧头帧尾
物理层: 10101010100011010... (比特流)

接收方则是逆向解封装,像剥洋葱一样一层层去掉头部。

四、TCP 详解(传输层核心)

1. TCP 头部格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

2. 关键字段

  • 源端口、目的端口:区分应用
  • 序列号:标识数据字节位置
  • 确认号:期望收到的下一个字节
  • 窗口大小:流量控制
  • 标志位:SYN、ACK、FIN、RST 等

3. 三次握手(建立连接)

1
2
3
4
5
6
7
8
Client                          Server
|--- SYN, seq=x -------------->|
| |
|<-- SYN+ACK, seq=y, ack=x+1 --|
| |
|--- ACK, seq=x+1, ack=y+1 --->|
| |
[连接建立]

为什么要三次而不是两次?

为了防止已失效的连接请求突然传到服务器导致错误。如果是两次,网络延迟的旧请求到达服务器,服务器以为建立连接但客户端已经放弃,造成资源浪费。

4. 四次挥手(断开连接)

1
2
3
4
5
6
7
8
9
10
Client                          Server
|--- FIN, seq=x -------------->|
| |
|<-- ACK, ack=x+1 -------------|
| |
|<-- FIN, seq=y ---------------|
| |
|--- ACK, ack=y+1 ------------>|
| |
[等待 2MSL 后关闭]

为什么是四次?

因为 TCP 是全双工的,客户端说”我说完了”,服务器也要说”我也说完了”。两次只能关一个方向。

5. 状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        LISTEN
| SYN
v
+-- SYN_SENT ---+
| | SYN+ACK
v v
SYN_RCVD <----- SYN_RCVD
| ACK | ACK
v v
ESTABLISHED ESTABLISHED
| FIN
v
FIN_WAIT_1 ---+
| ACK | FIN
v v
FIN_WAIT_2 CLOSE_WAIT
| FIN | FIN+ACK
v v
TIME_WAIT LAST_ACK
| | ACK
+--- CLOSED <---+

6. 流量控制(滑动窗口)

问题:发送方太快,接收方来不及处理。

解决:接收方告诉发送方自己的窗口大小(缓冲区剩余空间)。

1
2
接收方窗口 = 64KB
发送方最多发送 64KB 数据,等 ACK 后才能发更多

7. 拥塞控制

问题:网络本身拥塞,大量包丢失重传更糟。

解决:四个核心算法

  • 慢启动:从 1 个 MSS 开始,每收到 ACK 翻倍(指数增长)
  • 拥塞避免:达到阈值后线性增长
  • 快重传:收到 3 个重复 ACK 立即重传
  • 快恢复:跳过慢启动,直接进入拥塞避免
1
2
3
4
5
6
7
8
9
10
cwnd
^
| /\
| / \ ← 拥塞发生,阈值减半
| / \
| / \____ 慢启动阈值
| / \
| / \____ 拥塞避免(线性)
| /
+-------------------------> 时间

8. 抓包实战

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装 tcpdump
yum install -y tcpdump

# 抓取 HTTP 请求
tcpdump -i eth0 port 80 -A -s 0

# 抓 TCP 三次握手
tcpdump -i eth0 port 80 -nn

# 输出示例
12:00:00.000 IP 192.168.1.10.54321 > 192.168.1.20.80: Flags [S], seq 100
12:00:00.001 IP 192.168.1.20.80 > 192.168.1.10.54321: Flags [S.], seq 200, ack 101
12:00:00.002 IP 192.168.1.10.54321 > 192.168.1.20.80: Flags [.], ack 201

Flags 含义:

  • S = SYN
  • . = ACK
  • F = FIN
  • R = RST
  • P = PSH(推送数据)

五、UDP 详解

UDP(User Datagram Protocol)极简:

1
2
3
4
5
+----------+----------+----------+----------+
| Src Port | Dst Port | Length | Checksum |
+----------+----------+----------+----------+
| Data |
+--------------------------------------+

UDP 特点

  • 无连接:直接发,不握手
  • 不可靠:不保证送达、不保证顺序
  • 无流量控制:发就完了
  • 轻量:头部只有 8 字节

适用场景

  • DNS 查询
  • 视频/语音通话(偶尔丢包不致命)
  • 实时游戏
  • 广播/组播

UDP 真的会”丢包”吗?

会,而且 UDP 也不通知你。靠应用层处理:

  • 前向纠错(FEC)
  • 重传请求(ARQ)
  • 冗余编码

六、IP 协议(网络层)

1. IP 地址

IPv4:32 位,4 段十进制,共 43 亿个地址。

1
2
3
4
5
6
# IP 地址分类
A 类:1.0.0.0 - 126.255.255.255 (大型网络)
B 类:128.0.0.0 - 191.255.255.255 (中型)
C 类:192.0.0.0 - 223.255.255.255 (小型)
D 类:224.0.0.0 - 239.255.255.255 (组播)
E 类:240.0.0.0 - 255.255.255.255 (实验)

2. 子网掩码

1
2
255.255.255.0 = /24 = 前 24 位是网络号,后 8 位是主机号
192.168.1.0/24:网络 192.168.1.0,主机 1-254

3. CIDR 与 VLSM

无类域间路由,灵活划分网络。

4. IPv6

128 位,理论上 2^128 个地址,几乎用不完。

1
2001:0db8:85a3:0000:0000:8a2e:0370:7334

七、应用层协议

HTTP 演进史

1
2
3
4
5
HTTP/0.9 (1991):只有 GET,纯文本
HTTP/1.0 (1996):支持 POST、HEAD、状态码
HTTP/1.1 (1997):持久连接、管道、分块传输
HTTP/2 (2015):二进制、多路复用、HPACK 压缩
HTTP/3 (2018):基于 QUIC(UDP),彻底解决队头阻塞

HTTP 请求流程

1
浏览器 → DNS 解析 → TCP 连接 → 发送请求 → 接收响应 → 渲染页面

HTTPS = HTTP + TLS

1
2
3
4
5
6
7
Client                    Server
|--- Client Hello ------->| (支持的加密算法、随机数)
|<-- Server Hello --------| (选定的算法、证书)
|--- Key Exchange ------->| (用证书公钥加密 pre-master secret)
|<-- Finished ------------|
|--- Finished ----------->|
| [加密通信开始] |

TLS 1.3 把握手从 2-RTT 降到 1-RTT,甚至 0-RTT。

八、DNS 详解

1. 域名层级

1
2
3
4
.           (根域)
└── com (顶级域 TLD)
└── example.com (二级域)
└── www.example.com (子域)

2. 解析过程

1
2
浏览器缓存 → 系统缓存 → hosts →  LocalDNS → 
根 DNS → 顶级 DNS → 权威 DNS → 返回 IP

3. 记录类型

  • A:域名 → IPv4
  • AAAA:域名 → IPv6
  • CNAME:域名 → 域名(别名)
  • MX:邮件服务器
  • NS:权威 DNS 服务器
  • TXT:任意文本(SPF、DKIM 验证)

4. DNS 命令实战

1
2
3
4
5
6
7
8
9
10
11
12
# 查询 A 记录
dig example.com

# 指定 DNS 服务器
dig @8.8.8.8 example.com

# 追踪解析过程
dig +trace example.com

# 短格式
nslookup example.com
host example.com

九、网络排查工具

1. ping

测试连通性。

1
2
ping -c 4 example.com
# -c 4:发 4 个包

2. traceroute

查看路径。

1
2
traceroute example.com
# 看经过的路由节点

3. netstat / ss

查看连接。

1
2
ss -tulnp          # 监听端口
ss -tan | head # 已建立的 TCP 连接

4. tcpdump

抓包分析。

1
tcpdump -i any host 8.8.8.8 and port 53

5. Wireshark

图形化抓包工具,网络协议学习的瑞士军刀

十、性能优化实战

1. TCP 优化参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# /etc/sysctl.conf

# 增大半连接队列(SYN)
net.ipv4.tcp_max_syn_backlog = 65535

# 复用 TIME_WAIT 连接
net.ipv4.tcp_tw_reuse = 1

# 快速回收 TIME_WAIT
net.ipv4.tcp_tw_recycle = 1 # 注意:NAT 环境下要关

# 增大全连接队列
net.core.somaxconn = 65535

# 增大发送/接收缓冲区
net.ipv4.tcp_rmem = 4096 87380 6291456
net.ipv4.tcp_wmem = 4096 65536 6291456

# 开启 TCP 拥塞控制算法
net.ipv4.tcp_congestion_control = bbr # 谷歌 BBR 算法

2. HTTP/2 优化

  • 多路复用:一个连接并发多个请求
  • 头部压缩:HPACK 算法
  • 服务端推送(已废弃)

3. CDN 加速

  • 静态资源分发到边缘节点
  • 智能调度到最近的节点
  • 减少回源

十一、安全相关

1. SYN Flood 攻击

攻击者发大量 SYN 不回 ACK,占满半连接队列。

防御:SYN Cookie(net.ipv4.tcp_syncookies = 1)、防火墙、专业 Anti-DDoS 设备。

2. ARP 欺骗

局域网内发送伪造 ARP 包,拦截流量。

防御:静态 ARP 绑定、ARP 防火墙。

3. HTTPS 中间人攻击

攻击者在客户端和服务端之间伪造证书。

防御:客户端校验证书、HSTS、Certificate Pinning。

十二、深入学习路径

推荐书籍

  • 《TCP/IP 详解 卷 1:协议》(W. Richard Stevens)
  • 《计算机网络:自顶向下方法》(Kurose)
  • 《HTTP 权威指南》(David Gourley)
  • 《图解 HTTP》(上野宣)

在线资源

实战

  1. 用 Wireshark 抓自己电脑的 HTTP 请求,逐字段分析
  2. 用 Python 写一个简单的 Socket 客户端/服务器
  3. 部署一个网站,自己抓包看完整过程

总结

TCP/IP 协议栈看似复杂,但核心思想很简单:

  • 分层:每层只管自己的事
  • 封装:发送时层层打包,接收时层层解包
  • 可靠性:TCP 用握手、确认、重传保证数据不丢
  • 效率:滑动窗口、拥塞控制优化传输

理解了这些,你再看任何网络问题:

  • 为什么 502? 后端没响应 → TCP 连接失败
  • 为什么慢? 网络拥塞或服务器处理慢
  • 为什么丢包? 路由器过载或链路不稳

网络协议是程序员的底层能力,越深入学习,你解决问题的能力就越强。