知识模块
☕ Java 知识模块
十四、网络编程
TCP 与 HTTP

TCP 与 HTTP

TCP/IP 协议栈和 HTTP 协议是网络编程的核心基础。深入理解 TCP 连接管理、可靠传输机制,以及 HTTP 协议的演进历程,是 Java 开发者进行网络编程、性能优化和问题排查的必备技能。

面试高频考点:TCP 三次握手/四次挥手、TCP 可靠传输机制、HTTP 各版本差异、HTTPS 原理、HTTP 状态码


一、TCP 协议概述

1.1 TCP/IP 协议栈

TCP/IP 是互联网的基础协议栈,分为四层:

┌─────────────────────────────────────────────────────────────┐
│                    TCP/IP 协议栈                             │
├─────────────────────────────────────────────────────────────┤
│  应用层        │  HTTP、FTP、SMTP、DNS、SSH                  │
├───────────────┼─────────────────────────────────────────────┤
│  传输层        │  TCP(可靠)、UDP(不可靠)                  │
├───────────────┼─────────────────────────────────────────────┤
│  网络层        │  IP、ICMP、ARP                              │
├───────────────┼─────────────────────────────────────────────┤
│  网络接口层    │  Ethernet、Wi-Fi、PPP                       │
└─────────────────────────────────────────────────────────────┘

1.2 TCP 特点

特性说明
面向连接通信前需要建立连接
可靠传输保证数据无差错、不丢失、不重复、按序到达
面向字节流把数据看成一连串无结构的字节流
全双工双向通信,双方可同时发送和接收
点对点每条 TCP 连接只能有两个端点

二、TCP 三次握手

2.1 三次握手过程

┌─────────────────────────────────────────────────────────────┐
│                    TCP 三次握手                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│      Client                                    Server       │
│        │                                         │          │
│        │          ──────── SYN ────────►         │          │
│        │          seq=x, SYN=1                   │          │
│        │                                         │          │
│        │          ◄─────── SYN+ACK ───────       │          │
│        │          seq=y, ack=x+1, SYN=1, ACK=1   │          │
│        │                                         │          │
│        │          ──────── ACK ────────►         │          │
│        │          seq=x+1, ack=y+1, ACK=1        │          │
│        │                                         │          │
│        │          连接建立完成                    │          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 三次握手详解

步骤名称说明
第一次SYN_SENT客户端发送 SYN 包,进入 SYN_SENT 状态
第二次SYN_RCVD服务端收到 SYN,回复 SYN+ACK,进入 SYN_RCVD 状态
第三次ESTABLISHED客户端收到 SYN+ACK,回复 ACK,进入 ESTABLISHED 状态

2.3 为什么是三次握手?

原因1:防止历史连接

假设采用两次握手:
                                    
  Client                    Server
    │                          │
    │── SYN(旧) ─────────────►│  ← 第一个 SYN 延迟到达
    │                          │    (客户端已关闭的请求)
    │                          │
    │◄───── SYN+ACK ──────────│  ← 服务端建立连接
    │                          │
    │   客户端发现是旧请求     │
    │   无法通知服务端关闭     │
    │                          │  ← 服务端资源浪费
                                    
三次握手可以让客户端确认服务端的 SYN+ACK
如果发现是旧请求,可以发送 RST 终止连接


原因2:同步双方初始序列号

TCP 是可靠传输,需要序列号来保证有序性
三次握手才能确保双方的初始序列号都被确认

  Client                    Server
    │                          │
    │── SYN, seq=x ──────────►│  第一次:服务端确认 x
    │                          │
    │◄── SYN+ACK, seq=y ──────│  第二次:客户端确认 y
    │                          │
    │── ACK, ack=y+1 ────────►│  第三次:服务端确认客户端收到 y

2.4 半连接队列与全连接队列

┌─────────────────────────────────────────────────────────────┐
│                    TCP 连接队列                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Client                Server                              │
│     │                     │                                 │
│     │── SYN ─────────────►│                                 │
│     │                     ▼                                 │
│     │            ┌─────────────────┐                       │
│     │            │  半连接队列      │  SYN_RCVD 状态        │
│     │            │  (SYN Queue)    │  存储 SYN 请求        │
│     │            └────────┬────────┘                       │
│     │                     │                                 │
│     │◄── SYN+ACK ────────│                                 │
│     │                     │                                 │
│     │── ACK ─────────────►│                                 │
│     │                     ▼                                 │
│     │            ┌─────────────────┐                       │
│     │            │  全连接队列      │  ESTABLISHED 状态     │
│     │            │  (Accept Queue) │  等待应用 accept()    │
│     │            └─────────────────┘                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
队列说明溢出后果
半连接队列存放 SYN_RCVD 状态的连接SYN Flood 攻击利用此队列
全连接队列存放 ESTABLISHED 状态的连接新连接被丢弃或发送 RST

2.5 SYN Flood 攻击与防御

SYN Flood 攻击原理:
攻击者发送大量 SYN 包,但不回复 ACK
导致半连接队列溢出,正常连接无法建立

防御措施:

1. SYN Cookies
   - 不分配资源,通过加密算法生成序列号
   - 收到 ACK 时验证合法性

2. 增加半连接队列大小
   net.ipv4.tcp_max_syn_backlog = 8192

3. 缩短 SYN_RCVD 状态超时时间
   net.ipv4.tcp_synack_retries = 2

4. 启用 SYN Cookies
   net.ipv4.tcp_syncookies = 1

三、TCP 四次挥手

3.1 四次挥手过程

┌─────────────────────────────────────────────────────────────┐
│                    TCP 四次挥手                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│      Client                                    Server       │
│        │                                         │          │
│        │          ──────── FIN ────────►         │          │
│        │          seq=u, FIN=1, ACK=1           │          │
│        │          (主动关闭方)                   │          │
│        │                                         │          │
│        │          ◄─────── ACK ────────         │          │
│        │          seq=v, ack=u+1, ACK=1         │          │
│        │                                         │          │
│        │          ◄─────── FIN ────────         │          │
│        │          seq=w, FIN=1, ACK=1           │          │
│        │          (被动关闭方)                   │          │
│        │                                         │          │
│        │          ──────── ACK ────────►         │          │
│        │          seq=u+1, ack=w+1, ACK=1       │          │
│        │                                         │          │
│        │          等待 2MSL 后关闭               │          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 四次挥手状态变化

┌───────────────┐                    ┌───────────────┐
│    Client     │                    │    Server     │
├───────────────┤                    ├───────────────┤
│ ESTABLISHED   │                    │ ESTABLISHED   │
│       │       │                    │               │
│       ▼       │  ──── FIN ────►    │       │       │
│ FIN_WAIT_1    │                    │       ▼       │
│       │       │  ◄─── ACK ────     │ CLOSE_WAIT    │
│       ▼       │                    │       │       │
│ FIN_WAIT_2    │                    │       ▼       │
│       │       │  ◄─── FIN ────     │ LAST_ACK      │
│       ▼       │                    │       │       │
│ TIME_WAIT     │  ──── ACK ────►    │       ▼       │
│       │       │                    │    CLOSED     │
│       ▼       │                    │               │
│    CLOSED     │                    │               │
└───────────────┘                    └───────────────┘

3.3 为什么是四次挥手?

原因:TCP 是全双工通信

每个方向的连接需要单独关闭:

  Client                              Server
    │                                    │
    │───── FIN ────────►│  Client → Server 方向关闭
    │                   │  Server 不再接收 Client 数据
    │                   │  但 Server 还可以发送数据
    │◄──── ACK ─────────│
    │                   │
    │                   │  Server 发送剩余数据...
    │                   │
    │◄──── FIN ─────────│  Server → Client 方向关闭
    │───── ACK ────────►│
    │                                    │

为什么不能像三次握手那样合并?

三次握手时:
  - 服务端的 SYN 和 ACK 可以合并发送(SYN+ACK)

四次挥手时:
  - 服务端收到 FIN 后,可能还有数据要发送
  - 必须等数据发送完才能发送自己的 FIN
  - 所以 ACK 和 FIN 分开发送

3.4 TIME_WAIT 状态

为什么需要 TIME_WAIT?

1. 确保最后的 ACK 能到达服务端
   - 如果 ACK 丢失,服务端会重传 FIN
   - TIME_WAIT 允许重传 ACK

2. 等待旧连接的延迟数据消失
   - 防止旧连接的数据被新连接接收

为什么是 2MSL?

MSL (Maximum Segment Lifetime) = 报文最大生存时间

  Client                              Server
    │                                    │
    │◄──── FIN ──────────│
    │───── ACK ──────────►│  ACK 可能丢失
    │                   │
    │                   │  等待 1 MSL
    │◄──── FIN ─────────│  Server 重传 FIN
    │                   │
    │───── ACK ──────────►│  重传 ACK
    │                   │
    │  等待 1 MSL       │  确保新 ACK 到达
    │                                    │

总共等待 2 MSL,确保可靠关闭

3.5 TIME_WAIT 过多的问题

# 查看 TIME_WAIT 数量
netstat -an | grep TIME_WAIT | wc -l
 
# 问题:
# 1. 占用端口资源(客户端)
# 2. 占用内存资源
 
# 解决方案:
 
# 1. 开启端口复用
net.ipv4.tcp_tw_reuse = 1
 
# 2. 开启快速回收(可能导致问题)
net.ipv4.tcp_tw_recycle = 1  # 已废弃
 
# 3. 减少 TIME_WAIT 时间
net.ipv4.tcp_fin_timeout = 30
 
# 4. 优化最大连接数
net.ipv4.tcp_max_tw_buckets = 5000

四、TCP 可靠传输机制

4.1 序列号与确认应答

┌─────────────────────────────────────────────────────────────┐
│                    TCP 序列号机制                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Sender                                     Receiver       │
│     │                                           │           │
│     │─────── seq=1, data ─────────────────────►│           │
│     │                                           │           │
│     │◄───────────── ack=2 ─────────────────────│           │
│     │                                           │           │
│     │─────── seq=2, data ─────────────────────►│           │
│     │                                           │           │
│     │◄───────────── ack=3 ─────────────────────│           │
│     │                                           │           │
│                                                             │
│   seq:数据第一个字节的序号                                  │
│   ack:期望收到的下一个字节的序号                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 超时重传

┌─────────────────────────────────────────────────────────────┐
│                    TCP 超时重传                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Sender                                     Receiver       │
│     │                                           │           │
│     │─────── seq=1, data ─────────────────────►│  数据丢失  │
│     │     ×                                     │           │
│     │                                           │           │
│     │     等待 RTO 时间                         │           │
│     │                                           │           │
│     │─────── seq=1, data ─────────────────────►│  重传      │
│     │                                           │           │
│     │◄───────────── ack=2 ─────────────────────│           │
│     │                                           │           │
│                                                             │
│   RTO (Retransmission Timeout):重传超时时间                 │
│   RTO 应略大于 RTT (Round-Trip Time)                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

RTO 计算(Karn 算法)

RTO 计算:

1. 测量 RTT 样本
   RTT_sample = 收到 ACK 的时间 - 发送数据的时间

2. 计算加权平均 RTT
   RTT_SRTT = (1 - α) × RTT_SRTT + α × RTT_sample
   α 通常为 0.125

3. 计算 RTT 偏差
   RTT_VAR = (1 - β) × RTT_VAR + β × |RTT_SRTT - RTT_sample|
   β 通常为 0.25

4. 计算 RTO
   RTO = RTT_SRTT + 4 × RTT_VAR

注意:重传的数据不参与 RTT 计算(Karn 算法)

4.3 快速重传

┌─────────────────────────────────────────────────────────────┐
│                    TCP 快速重传                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Sender                                     Receiver       │
│     │                                           │           │
│     │─────── seq=1 ───────────────────────────►│           │
│     │◄───────────── ack=2 ─────────────────────│           │
│     │                                           │           │
│     │─────── seq=2 ────────× (丢失)             │           │
│     │                                           │           │
│     │─────── seq=3 ───────────────────────────►│           │
│     │◄───────────── ack=2 ─────────────────────│  期望收2  │
│     │                                           │           │
│     │─────── seq=4 ───────────────────────────►│           │
│     │◄───────────── ack=2 ─────────────────────│  重复 ACK │
│     │                                           │           │
│     │─────── seq=5 ───────────────────────────►│           │
│     │◄───────────── ack=2 ─────────────────────│  重复 ACK │
│     │                                           │           │
│     │  收到 3 个重复 ACK,立即重传 seq=2        │           │
│     │                                           │           │
│     │─────── seq=2 ───────────────────────────►│  快速重传 │
│     │◄───────────── ack=6 ─────────────────────│           │
│                                                             │
│   快速重传:收到 3 个重复 ACK,立即重传,不等超时            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.4 滑动窗口

┌─────────────────────────────────────────────────────────────┐
│                    TCP 滑动窗口                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   发送方窗口                                                 │
│   ┌─────────────────────────────────────────────────────┐  │
│   │    已发送确认    │    已发送未确认    │  可用窗口   │  │
│   │  ┌────────────┐ │ ┌───────────────┐ │┌───────────┐│  │
│   │  │ 1  2  3  4 │ │ │ 5  6  7  8    │ ││ 9  10 ... ││  │
│   │  └────────────┘ │ └───────────────┘ │└───────────┘│  │
│   │   ←────── 已发送并收到确认 ──────→  │ ← 可发送 → │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   接收方窗口                                                 │
│   ┌─────────────────────────────────────────────────────┐  │
│   │   已接收处理   │    可接收窗口                       │  │
│   │ ┌────────────┐│┌────────────────────────────────────┐│  │
│   │ │ 1  2  3  4 │││ 5  6  7  8  9  10  ...            ││  │
│   │ └────────────┘│└────────────────────────────────────┘│  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   窗口大小由接收方通告(Flow Control)                       │
│   Window Size = 接收缓冲区可用空间                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.5 选择性确认(SACK)

┌─────────────────────────────────────────────────────────────┐
│                    TCP SACK                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   传统 ACK:只能告知丢失的第一个包                           │
│   SACK:可以告知已收到的多个数据块                           │
│                                                             │
│   Sender                                     Receiver       │
│     │                                           │           │
│     │─────── seq=1 ───────────────────────────►│           │
│     │─────── seq=2 ────────× (丢失)             │           │
│     │─────── seq=3 ───────────────────────────►│           │
│     │─────── seq=4 ────────× (丢失)             │           │
│     │─────── seq=5 ───────────────────────────►│           │
│     │                                           │           │
│     │◄── ack=2, SACK=[3,4], SACK=[5,6] ────────│           │
│     │                                           │           │
│     │  只需重传 seq=2 和 seq=4                  │           │
│     │                                           │           │
│                                                             │
│   SACK 选项格式:                                            │
│   ┌────────┬────────┬──────────────┬──────────────┐         │
│   │ Kind=5 │ Length │ Left Edge 1  │ Right Edge 1 │ ...     │
│   └────────┴────────┴──────────────┴──────────────┘         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

五、TCP 流量控制与拥塞控制

5.1 流量控制

┌─────────────────────────────────────────────────────────────┐
│                    TCP 流量控制                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   目的:防止发送方发太快,接收方来不及处理                    │
│   方法:接收方通告窗口大小                                   │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                    接收方缓冲区                       │  │
│   │   ┌────────────────────────────────────────────────┐│  │
│   │   │████████████████████│                      可用  ││  │
│   │   └────────────────────────────────────────────────┘│  │
│   │        已接收未处理           ← 接收窗口 →           │  │
│   │        rwnd = 缓冲区大小 - 已接收未处理              │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   零窗口探测:                                               │
│   当 rwnd=0 时,发送方定时发送 1 字节探测包                  │
│   接收方回复当前窗口大小                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.2 拥塞控制

┌─────────────────────────────────────────────────────────────┐
│                    TCP 拥塞控制                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   目的:防止过多数据注入网络,避免网络拥塞                    │
│   方法:发送方维护拥塞窗口 (cwnd)                            │
│                                                             │
│   发送窗口 = min(cwnd, rwnd)                                │
│                                                             │
│   四种算法:                                                 │
│                                                             │
│   1. 慢启动 (Slow Start)                                    │
│      cwnd 初始 = 1 MSS                                      │
│      每收到一个 ACK,cwnd 加倍                              │
│      指数增长:1 → 2 → 4 → 8 → ...                          │
│                                                             │
│   2. 拥塞避免 (Congestion Avoidance)                        │
│      当 cwnd >= ssthresh 时                                 │
│      每个 RTT,cwnd + 1 MSS                                 │
│      线性增长:... → 8 → 9 → 10 → ...                       │
│                                                             │
│   3. 快速重传 (Fast Retransmit)                             │
│      收到 3 个重复 ACK                                      │
│      立即重传,不等超时                                      │
│                                                             │
│   4. 快速恢复 (Fast Recovery)                               │
│      ssthresh = cwnd / 2                                    │
│      cwnd = ssthresh + 3 MSS                                │
│      进入拥塞避免阶段                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.3 拥塞控制状态机

┌─────────────────────────────────────────────────────────────┐
│                    TCP 拥塞控制状态机                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                    ┌──────────────┐                         │
│                    │   慢启动      │                         │
│                    │  (cwnd×2)    │                         │
│                    └──────┬───────┘                         │
│                           │                                 │
│              cwnd >= ssthresh                              │
│                           │                                 │
│                           ▼                                 │
│                    ┌──────────────┐                         │
│         ┌─────────│  拥塞避免     │◄─────────┐              │
│         │         │  (cwnd+1)    │          │              │
│         │         └──────┬───────┘          │              │
│         │                │                   │              │
│         │    ┌───────────┴───────────┐      │              │
│         │    │                       │      │              │
│    超时  │    │  3 个重复 ACK         │      │              │
│         │    │                       │      │              │
│         │    ▼                       ▼      │              │
│         │  ┌──────────────┐   ┌──────────────┐             │
│         │  │  快速重传     │──►│  快速恢复     │             │
│         │  │              │   │  (cwnd/2+3)  │             │
│         │  └──────────────┘   └──────────────┘             │
│         │                                          │        │
│         │               收到新数据的 ACK          │        │
│         │                                          │        │
│         ▼                                          │        │
│   ssthresh = cwnd/2                               │        │
│   cwnd = 1 MSS                                     │        │
│   回到慢启动                                        │        │
│                                                            │
└─────────────────────────────────────────────────────────────┘

5.4 流量控制 vs 拥塞控制

对比项流量控制拥塞控制
目的保护接收方保护网络
对象点对点全局网络
机制滑动窗口拥塞窗口
反馈接收方通告网络拥塞信号

六、HTTP 协议概述

6.1 HTTP 基本概念

HTTP (HyperText Transfer Protocol) 是应用层协议,基于 TCP,用于 Web 通信。

┌─────────────────────────────────────────────────────────────┐
│                    HTTP 请求-响应模型                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│      Client (Browser)                      Server           │
│            │                                 │              │
│            │  ──────── Request ────────────► │              │
│            │                                 │              │
│            │  ◄─────── Response ─────────── │              │
│            │                                 │              │
│                                                             │
│   请求:                                                     │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ GET /index.html HTTP/1.1                            │  │
│   │ Host: www.example.com                               │  │
│   │ User-Agent: Mozilla/5.0                             │  │
│   │ Accept: text/html                                   │  │
│   │                                                     │  │
│   │ (请求体 - 可选)                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   响应:                                                     │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ HTTP/1.1 200 OK                                     │  │
│   │ Content-Type: text/html                             │  │
│   │ Content-Length: 1234                                │  │
│   │                                                     │  │
│   │ <html>...</html>                                    │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 HTTP 请求方法

方法说明是否有请求体
GET获取资源
POST提交数据
PUT更新资源
DELETE删除资源
HEAD获取响应头
OPTIONS获取支持的方法
PATCH部分更新

6.3 GET vs POST

对比项GETPOST
数据位置URL 中请求体中
数据长度受 URL 长度限制无限制
安全性参数暴露在 URL相对安全
缓存可被缓存不缓存
历史记录参数保留在浏览器历史不保留
幂等性幂等非幂等
书签可收藏为书签不可

七、HTTP 协议版本差异

7.1 HTTP 版本演进

┌─────────────────────────────────────────────────────────────┐
│                    HTTP 版本演进                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   HTTP/1.0 (1996)                                          │
│   ├── 短连接:每次请求需要新建 TCP 连接                      │
│   ├── 无法复用连接                                          │
│   └── 性能差                                                │
│                                                             │
│   HTTP/1.1 (1997)                                          │
│   ├── 持久连接:Connection: keep-alive                      │
│   ├── 管道化:可同时发送多个请求                            │
│   ├── Host 头:支持虚拟主机                                 │
│   └── 队头阻塞:响应必须按顺序                              │
│                                                             │
│   HTTP/2.0 (2015)                                          │
│   ├── 二进制分帧:提高解析效率                              │
│   ├── 多路复用:一个连接并行多个请求/响应                   │
│   ├── 头部压缩:HPACK 算法                                  │
│   └── 服务端推送:主动推送资源                              │
│                                                             │
│   HTTP/3.0 (2022)                                          │
│   ├── 基于 QUIC:UDP 替代 TCP                              │
│   ├── 解决队头阻塞:独立的流                                │
│   ├── 连接迁移:网络切换不断开                              │
│   └── 0-RTT:快速建立连接                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

7.2 HTTP/1.0 vs HTTP/1.1

HTTP/1.0:
┌─────────────────────────────────────────────────────────────┐
│  Client                                Server               │
│    │                                     │                   │
│    │── TCP 三次握手 ────────────────────►│                   │
│    │◄────────────────────────────────── │                   │
│    │                                     │                   │
│    │── Request 1 ──────────────────────►│                   │
│    │◄── Response 1 ─────────────────────│                   │
│    │                                     │                   │
│    │── TCP 四次挥手 ──────────────────►│                   │
│    │◄────────────────────────────────── │                   │
│    │                                     │                   │
│    │  (下一个请求需要重新建立连接)        │                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

HTTP/1.1 持久连接:
┌─────────────────────────────────────────────────────────────┐
│  Client                                Server               │
│    │                                     │                   │
│    │── TCP 三次握手 ────────────────────►│                   │
│    │                                     │                   │
│    │── Request 1 ──────────────────────►│                   │
│    │◄── Response 1 ─────────────────────│                   │
│    │                                     │                   │
│    │── Request 2 ──────────────────────►│  复用连接         │
│    │◄── Response 2 ─────────────────────│                   │
│    │                                     │                   │
│    │── Request 3 ──────────────────────►│                   │
│    │◄── Response 3 ─────────────────────│                   │
│    │                                     │                   │
│    │── Connection: close ──────────────►│                   │
│    │── TCP 四次挥手 ──────────────────►│                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

7.3 HTTP/1.1 队头阻塞

HTTP/1.1 管道化问题:

  Request 1 ────────────────────────────────────►
  Request 2 ────────────────────────────────────►
  Request 3 ────────────────────────────────────►
  
  ◄─────── Response 1 (耗时 2s) ────────────────
                    │ 等待...

  ◄─────── Response 2 (耗时 0.1s) ───────────────
                    │ 虽然 Response 2 早处理完
                    │ 但必须等 Response 1 先返回

  ◄─────── Response 3 (耗时 0.1s) ───────────────

问题:前面的响应慢,阻塞后面的响应

7.4 HTTP/2.0 多路复用

HTTP/2.0 多路复用:

┌─────────────────────────────────────────────────────────────┐
│                    二进制分帧层                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Stream 1: Frame 1, Frame 2, Frame 3                      │
│   Stream 2: Frame 1, Frame 2                                │
│   Stream 3: Frame 1, Frame 2, Frame 3, Frame 4             │
│                                                             │
│   ──────── 在一个 TCP 连接上交错传输 ────────►              │
│                                                             │
│   接收方根据 Stream ID 重新组装                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

特点:
1. 一个 TCP 连接可以并行多个请求/响应
2. 请求和响应可以交错发送
3. 解决了 HTTP 层的队头阻塞
4. 但 TCP 层仍可能阻塞(丢包导致)

7.5 HTTP/3.0 QUIC

┌─────────────────────────────────────────────────────────────┐
│                    HTTP/3.0 架构                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   传统 HTTP (TCP):                                          │
│   ┌────────────────────────────────────────────────────┐   │
│   │ HTTP/1.1 │ HTTP/2.0                                │   │
│   ├──────────┴─────────────────────────────────────────┤   │
│   │                    TCP                             │   │
│   ├────────────────────────────────────────────────────┤   │
│   │                    TLS                             │   │
│   ├────────────────────────────────────────────────────┤   │
│   │                    IP                              │   │
│   └────────────────────────────────────────────────────┘   │
│                                                             │
│   HTTP/3.0 (QUIC):                                          │
│   ┌────────────────────────────────────────────────────┐   │
│   │                   HTTP/3.0                          │   │
│   ├────────────────────────────────────────────────────┤   │
│   │                   QUIC                              │   │
│   │          (可靠性 + 加密 + 多路复用)                  │   │
│   ├────────────────────────────────────────────────────┤   │
│   │                    UDP                              │   │
│   ├────────────────────────────────────────────────────┤   │
│   │                    IP                              │   │
│   └────────────────────────────────────────────────────┘   │
│                                                             │
│   QUIC 优势:                                                │
│   1. 解决 TCP 队头阻塞:独立的 Stream                       │
│   2. 连接迁移:Connection ID 替代四元组                     │
│   3. 快速连接:0-RTT / 1-RTT                               │
│   4. 内置加密:TLS 1.3 集成                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

7.6 HTTP 版本对比总结

特性HTTP/1.0HTTP/1.1HTTP/2.0HTTP/3.0
连接方式短连接持久连接多路复用QUIC
队头阻塞HTTP层解决完全解决
头部压缩HPACKQPACK
二进制协议
服务端推送
传输层TCPTCPTCPUDP

八、HTTPS 原理

8.1 HTTP vs HTTPS

┌─────────────────────────────────────────────────────────────┐
│                    HTTP vs HTTPS                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   HTTP:                                                     │
│   ┌──────────┐     明文传输     ┌──────────┐               │
│   │  Client  │ ───────────────► │  Server  │               │
│   └──────────┘                  └──────────┘               │
│                                                             │
│   问题:                                                     │
│   - 数据可被窃听(明文传输)                                 │
│   - 数据可被篡改(无完整性校验)                             │
│   - 身份可被伪造(无身份验证)                               │
│                                                             │
│   HTTPS:                                                     │
│   ┌──────────┐     加密传输     ┌──────────┐               │
│   │  Client  │ ───────────────► │  Server  │               │
│   └──────────┘                  └──────────┘               │
│        │                             │                      │
│        └─────── TLS/SSL ─────────────┘                      │
│                                                             │
│   安全:                                                     │
│   - 加密:数据无法窃听                                       │
│   - 完整性:数据无法篡改                                     │
│   - 认证:确保服务器身份                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

8.2 TLS/SSL 握手过程

┌─────────────────────────────────────────────────────────────┐
│                    TLS 1.2 握手过程                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Client                                     Server         │
│     │                                           │           │
│     │── ClientHello ──────────────────────────►│           │
│     │   支持的加密套件、TLS版本、随机数         │           │
│     │                                           │           │
│     │◄── ServerHello ───────────────────────── │           │
│     │   选定的加密套件、TLS版本、随机数         │           │
│     │                                           │           │
│     │◄── Certificate ───────────────────────── │           │
│     │   服务器证书                              │           │
│     │                                           │           │
│     │◄── ServerHelloDone ───────────────────── │           │
│     │                                           │           │
│     │── ClientKeyExchange ────────────────────►│           │
│     │   加密的预主密钥                          │           │
│     │                                           │           │
│     │── ChangeCipherSpec ─────────────────────►│           │
│     │── Finished ─────────────────────────────►│           │
│     │                                           │           │
│     │◄── ChangeCipherSpec ──────────────────── │           │
│     │◄── Finished ──────────────────────────── │           │
│     │                                           │           │
│     │          开始加密通信                      │           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

8.3 TLS 1.3 握手优化

┌─────────────────────────────────────────────────────────────┐
│                    TLS 1.3 握手过程                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   TLS 1.2: 2 RTT                                            │
│   ────────────────────────────────────────────►             │
│   ◄────────────────────────────────────────────             │
│   ────────────────────────────────────────────►             │
│   ◄────────────────────────────────────────────             │
│                                                             │
│   TLS 1.3: 1 RTT                                            │
│   ────────────────────────────────────────────►             │
│   ◄────────────────────────────────────────────             │
│                                                             │
│   TLS 1.3 0-RTT (恢复会话):                                 │
│   ────────────────────────────────────────────►             │
│   (立即发送应用数据)                                         │
│                                                             │
│   优化措施:                                                 │
│   1. 精简加密套件:移除不安全的算法                          │
│   2. 合并消息:ClientHello 携带密钥材料                      │
│   3. PSK 恢复:支持 0-RTT                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

8.4 数字证书与 CA

┌─────────────────────────────────────────────────────────────┐
│                    数字证书验证链                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌──────────────┐                                         │
│   │   Root CA    │  根证书(内置在操作系统/浏览器)          │
│   │  (自签名)    │                                         │
│   └──────┬───────┘                                         │
│          │ 签发                                             │
│          ▼                                                  │
│   ┌──────────────┐                                         │
│   │ Intermediate │  中间证书                                │
│   │     CA       │                                         │
│   └──────┬───────┘                                         │
│          │ 签发                                             │
│          ▼                                                  │
│   ┌──────────────┐                                         │
│   │   Server     │  服务器证书                              │
│   │ Certificate  │  (www.example.com)                      │
│   └──────────────┘                                         │
│                                                             │
│   验证过程:                                                 │
│   1. 浏览器收到服务器证书                                    │
│   2. 用中间 CA 公钥验证服务器证书签名                        │
│   3. 用根 CA 公钥验证中间 CA 证书签名                        │
│   4. 根 CA 证书在信任列表中,验证通过                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

8.5 对称加密 vs 非对称加密

对比项对称加密非对称加密
密钥加密解密用同一密钥公钥加密,私钥解密
速度
安全性密钥传输风险安全
算法AES、DES、ChaCha20RSA、ECC
用途数据加密密钥交换、数字签名

HTTPS 混合加密

HTTPS 使用混合加密:

1. 握手阶段:非对称加密
   - 安全交换对称密钥
   - 使用 RSA 或 ECDHE

2. 数据传输阶段:对称加密
   - 使用协商好的对称密钥
   - 高效加密大量数据

混合加密 = 非对称加密的安全性 + 对称加密的高效性

九、HTTP 状态码详解

9.1 状态码分类

类别说明常见状态码
1xx信息响应100 Continue
2xx成功200 OK, 201 Created, 204 No Content
3xx重定向301 永久重定向, 302 临时重定向, 304 Not Modified
4xx客户端错误400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
5xx服务端错误500 Internal Error, 502 Bad Gateway, 503 Service Unavailable

9.2 常见状态码详解

┌─────────────────────────────────────────────────────────────┐
│                    常见 HTTP 状态码                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   2xx 成功                                                   │
│   ├── 200 OK:请求成功                                       │
│   ├── 201 Created:创建成功(POST)                          │
│   ├── 202 Accepted:已接受,异步处理中                       │
│   └── 204 No Content:成功但无返回内容                       │
│                                                             │
│   3xx 重定向                                                 │
│   ├── 301 Moved Permanently:永久重定向                      │
│   │   SEO 权重转移,浏览器缓存                               │
│   ├── 302 Found:临时重定向                                  │
│   │   SEO 权重不转移,用于临时跳转                           │
│   ├── 304 Not Modified:资源未修改                           │
│   │   协商缓存命中,使用本地缓存                             │
│   └── 307/308:保持请求方法的重定向                          │
│                                                             │
│   4xx 客户端错误                                             │
│   ├── 400 Bad Request:请求格式错误                          │
│   ├── 401 Unauthorized:未认证                               │
│   ├── 403 Forbidden:已认证但无权限                          │
│   ├── 404 Not Found:资源不存在                              │
│   ├── 405 Method Not Allowed:方法不允许                     │
│   └── 429 Too Many Requests:请求过于频繁                    │
│                                                             │
│   5xx 服务端错误                                             │
│   ├── 500 Internal Server Error:服务器内部错误              │
│   ├── 502 Bad Gateway:网关错误(上游服务不可用)            │
│   ├── 503 Service Unavailable:服务不可用                    │
│   └── 504 Gateway Timeout:网关超时                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

9.3 301 vs 302 vs 307

┌─────────────────────────────────────────────────────────────┐
│                    重定向状态码对比                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   301 Moved Permanently                                     │
│   - 永久重定向                                               │
│   - 浏览器会缓存新地址                                       │
│   - SEO 权重转移到新地址                                     │
│   - POST → GET(历史遗留问题)                               │
│                                                             │
│   302 Found                                                 │
│   - 临时重定向                                               │
│   - 浏览器不缓存                                             │
│   - SEO 权重不转移                                          │
│   - POST → GET(历史遗留问题)                               │
│                                                             │
│   307 Temporary Redirect                                    │
│   - 临时重定向(严格版)                                      │
│   - 保持请求方法不变                                         │
│   - POST → POST                                             │
│                                                             │
│   308 Permanent Redirect                                    │
│   - 永久重定向(严格版)                                      │
│   - 保持请求方法不变                                         │
│   - POST → POST                                             │
│                                                             │
│   使用场景:                                                 │
│   - 网站永久迁移:301                                        │
│   - 临时维护页面:302                                        │
│   - 表单提交后重定向:307                                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

9.4 401 vs 403

状态码含义场景
401未认证未登录、Token 无效
403已认证但无权限已登录但权限不足
示例:

用户访问管理后台:

1. 未登录
   GET /admin
   Response: 401 Unauthorized
   → 跳转到登录页

2. 已登录普通用户
   GET /admin
   Response: 403 Forbidden
   → 显示无权限页面

3. 已登录管理员
   GET /admin
   Response: 200 OK
   → 正常显示管理后台

十、HTTP 请求头与响应头

10.1 常用请求头

┌─────────────────────────────────────────────────────────────┐
│                    常用 HTTP 请求头                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   通用请求头:                                               │
│   ├── Host: www.example.com          # 目标主机             │
│   ├── User-Agent: Mozilla/5.0        # 客户端标识           │
│   ├── Accept: text/html              # 可接受的响应类型      │
│   ├── Accept-Language: zh-CN         # 语言偏好             │
│   ├── Accept-Encoding: gzip, br      # 支持的压缩算法        │
│   └── Connection: keep-alive         # 连接控制             │
│                                                             │
│   缓存相关:                                                 │
│   ├── If-Modified-Since: date        # 条件请求             │
│   ├── If-None-Match: "etag"          # ETag 验证            │
│   └── Cache-Control: no-cache        # 缓存控制             │
│                                                             │
│   认证相关:                                                 │
│   ├── Authorization: Bearer token    # 认证令牌             │
│   └── Cookie: sessionid=xxx          # Cookie               │
│                                                             │
│   内容相关:                                                 │
│   ├── Content-Type: application/json # 请求体类型           │
│   ├── Content-Length: 1234           # 请求体长度           │
│   └── Content-Encoding: gzip         # 请求体编码           │
│                                                             │
│   CORS 相关:                                                │
│   ├── Origin: https://example.com    # 请求来源             │
│   └── Access-Control-Request-Method  # 预检请求方法         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

10.2 常用响应头

┌─────────────────────────────────────────────────────────────┐
│                    常用 HTTP 响应头                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   通用响应头:                                               │
│   ├── Server: nginx                  # 服务器标识           │
│   ├── Date: Mon, 01 Jan 2024         # 响应时间             │
│   └── Connection: keep-alive         # 连接控制             │
│                                                             │
│   内容相关:                                                 │
│   ├── Content-Type: text/html        # 响应体类型           │
│   ├── Content-Length: 1234           # 响应体长度           │
│   ├── Content-Encoding: gzip         # 压缩算法             │
│   └── Content-Disposition: attachment# 下载文件名           │
│                                                             │
│   缓存相关:                                                 │
│   ├── Cache-Control: max-age=3600   # 缓存时间             │
│   ├── ETag: "abc123"                 # 资源版本标识         │
│   ├── Last-Modified: date            # 最后修改时间         │
│   └── Expires: date                  # 过期时间             │
│                                                             │
│   安全相关:                                                 │
│   ├── Strict-Transport-Security      # HSTS                │
│   ├── X-Content-Type-Options: nosniff# MIME 类型嗅探禁止    │
│   ├── X-Frame-Options: DENY          # 防止点击劫持         │
│   └── X-XSS-Protection: 1; mode=block# XSS 保护            │
│                                                             │
│   CORS 相关:                                                │
│   ├── Access-Control-Allow-Origin    # 允许的源             │
│   ├── Access-Control-Allow-Methods   # 允许的方法           │
│   └── Access-Control-Allow-Headers   # 允许的头             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

10.3 Cache-Control 详解

┌─────────────────────────────────────────────────────────────┐
│                    Cache-Control 指令                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   请求头指令:                                               │
│   ├── no-cache          # 强制向服务器验证                   │
│   ├── no-store          # 不缓存任何内容                     │
│   ├── max-age=seconds   # 可接受的缓存时间                   │
│   └── only-if-cached    # 只使用缓存                         │
│                                                             │
│   响应头指令:                                               │
│   ├── public            # 可被任何缓存存储                   │
│   ├── private           # 只能被浏览器缓存                   │
│   ├── no-cache          # 使用前必须验证                     │
│   ├── no-store          # 不缓存                             │
│   ├── max-age=seconds   # 缓存有效时间                       │
│   ├── must-revalidate   # 过期后必须验证                     │
│   └── immutable         # 资源永不变化                       │
│                                                             │
│   示例:                                                     │
│   Cache-Control: public, max-age=31536000, immutable        │
│   # 静态资源:缓存一年,永不重新验证                         │
│                                                             │
│   Cache-Control: no-cache                                  │
│   # 每次使用前必须向服务器验证                               │
│                                                             │
│   Cache-Control: no-store                                  │
│   # 敏感数据,禁止缓存                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

10.4 强缓存 vs 协商缓存

┌─────────────────────────────────────────────────────────────┐
│                    HTTP 缓存策略                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   强缓存(不发请求):                                       │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ Client                     Server                    │  │
│   │   │                          │                       │  │
│   │   │── GET /app.js ──────────►│                       │  │
│   │   │                          │                       │  │
│   │   │  检查本地缓存            │                       │  │
│   │   │  Cache-Control 未过期    │                       │  │
│   │   │                          │                       │  │
│   │   │  直接使用缓存 (200 OK    │                       │  │
│   │   │  from disk/memory cache) │                       │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   响应头:Cache-Control, Expires                           │
│                                                             │
│   协商缓存(发请求验证):                                   │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ Client                     Server                    │  │
│   │   │                          │                       │  │
│   │   │── GET /app.js ──────────►│                       │  │
│   │   │  If-None-Match: "etag"   │                       │  │
│   │   │                          │                       │  │
│   │   │                          │ 资源未修改             │  │
│   │   │◄── 304 Not Modified ────│                       │  │
│   │   │                          │                       │  │
│   │   │  使用本地缓存            │                       │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   响应头:ETag + If-None-Match                             │
│           Last-Modified + If-Modified-Since                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

十一、常见面试题

Q1: TCP 三次握手为什么不能是两次?

A:

  1. 防止历史连接:两次握手无法让客户端拒绝服务端的旧连接请求
  2. 同步序列号:TCP 需要确认双方的初始序列号,两次握手只能确认一个方向的序列号
  3. 防止资源浪费:如果只有两次握手,服务端收到 SYN 就建立连接,容易受到 SYN Flood 攻击

Q2: TCP 四次挥手为什么客户端要等待 2MSL?

A:

  1. 确保最后的 ACK 到达:如果 ACK 丢失,服务端会重发 FIN,2MSL 时间足够让客户端收到重发的 FIN 并重发 ACK
  2. 等待旧数据消失:确保旧连接的数据在网络中消失,不会被新连接接收

Q3: TCP 如何保证可靠传输?

A:

  1. 序列号和确认应答:保证数据有序、无丢失
  2. 超时重传:丢失的数据自动重传
  3. 快速重传:收到 3 个重复 ACK 立即重传
  4. 流量控制:滑动窗口防止接收方溢出
  5. 拥塞控制:慢启动、拥塞避免、快速恢复防止网络拥塞
  6. 校验和:检测数据传输错误

Q4: HTTP/1.1 如何解决队头阻塞?

A: HTTP/1.1 无法完全解决队头阻塞,只能缓解:

  1. 持久连接:复用 TCP 连接,减少握手开销
  2. 管道化:可以连续发送多个请求,但响应必须按序返回
  3. 实际方案:浏览器对同一域名开启多个 TCP 连接(通常 6 个)

真正的解决方案是 HTTP/2.0 的多路复用。

Q5: HTTPS 是如何保证安全的?

A:

  1. 加密:混合加密机制,握手用非对称加密,传输用对称加密
  2. 完整性:消息认证码(MAC)保证数据不被篡改
  3. 认证:数字证书 + CA 链验证服务器身份

Q6: GET 和 POST 有什么区别?

A:

对比项GETPOST
参数位置URL 中请求体中
参数长度受限无限制
安全性参数暴露相对安全
缓存可缓存不可缓存
幂等性幂等非幂等
历史记录保留不保留

Q7: 什么是 HTTP 的幂等性?

A: 幂等性指多次执行相同请求,结果与执行一次相同。

  • 幂等方法:GET、PUT、DELETE、HEAD、OPTIONS
  • 非幂等方法:POST
幂等示例:
DELETE /users/1  → 删除用户1,多次删除结果相同

非幂等示例:
POST /orders     → 创建订单,多次请求会创建多个订单

Q8: HTTP/2.0 相比 HTTP/1.1 有什么改进?

A:

  1. 二进制分帧:将报文分成更小的帧,提高解析效率
  2. 多路复用:一个连接可并行多个请求/响应,解决队头阻塞
  3. 头部压缩:HPACK 算法压缩请求头
  4. 服务端推送:主动推送客户端可能需要的资源
  5. 请求优先级:可以给请求设置优先级

Q9: 什么是跨域?如何解决?

A: 跨域是浏览器的同源策略限制,协议、域名、端口任一不同就是跨域。

解决方案:

  1. CORS:服务端设置 Access-Control-Allow-Origin
  2. 代理服务器:通过同源服务器转发请求
  3. JSONP:利用 script 标签(仅支持 GET)
  4. WebSocket:不受同源策略限制

Q10: 解释 TCP 的滑动窗口机制?

A: 滑动窗口是实现流量控制和可靠传输的核心机制:

  1. 发送方维护发送窗口,接收方维护接收窗口
  2. 接收方通过 ACK 通告接收窗口大小
  3. 发送方根据窗口大小控制发送速率
  4. 窗口可以向前滑动,实现连续的数据传输

十二、总结

知识点核心内容面试关键词
TCP 连接管理三次握手、四次挥手SYN Flood、TIME_WAIT、2MSL
TCP 可靠传输序列号、确认应答、重传超时重传、快速重传、SACK
TCP 流量/拥塞控制滑动窗口、拥塞窗口慢启动、拥塞避免、快速恢复
HTTP 协议请求响应、状态码、头部GET vs POST、缓存策略
HTTP 版本1.0/1.1/2.0/3.0多路复用、QUIC、队头阻塞
HTTPSTLS 握手、证书验证对称/非对称加密、CA

最佳实践清单

  • 理解 TCP 连接建立的完整过程
  • 掌握 TIME_WAIT 状态的意义和优化方法
  • 了解 TCP 拥塞控制算法
  • 熟悉 HTTP 各版本的差异
  • 掌握 HTTPS 的工作原理
  • 理解 HTTP 缓存策略
  • 能够排查网络连接问题

最后更新:2026年3月16日