文章

TCP-UDP与前端工程师需要掌握的网络基础

TCP-UDP与前端工程师需要掌握的网络基础

一句话概括

TCP(传输控制协议)和 UDP(用户数据报协议)是互联网传输层的两大基石:TCP 提供可靠、有序、拥塞控制的字节流服务(用于 HTTP、WebSocket),UDP 提供无连接、无可靠保证的数据报服务(用于 DNS 视频流/语音),理解它们的差异和适用场景是网络性能优化的前置知识。

背景与意义

为什么需要两种协议?

互联网的应用场景差异巨大:

1
2
3
4
5
6
7
8
9
HTTP 网页浏览:
"我需要每一个字节都正确到达,少一个都不行"
→ TCP 保证了数据的完整性和顺序性
→ 代价:连接建立慢(三次握手)、拥塞控制

视频直播 / 游戏:
"晚 500ms 到不如丢了重传,我要实时性!"
→ UDP 放弃可靠性,优先保证速度和实时性
→ 代价:数据包可能丢失或乱序

没有 UDP,实时应用就无法实现;没有 TCP,网页浏览和文件传输就无法保证正确性。

面试高频信号

TCP/UDP 在前端面试中出现频率相对较低,但在网络性能优化和安全方向面试中是常考题:

  • “TCP 的三次握手和四次挥手是什么?”
  • “TCP 和 UDP 的区别是什么?”
  • “HTTP 用的是 TCP 还是 UDP?WebSocket 呢?”

概念与定义

TCP 的核心特性

1
2
3
4
5
6
7
8
9
10
11
12
13
可靠传输(Reliable Transmission)
  ├─ 确认机制(ACK)
  ├─ 超时重传
  └─ 序列号(Sequence Number)
        │
有序传输(Ordered Delivery)
  └─ 按序号重组,丢弃重复包
        │
流量控制(Flow Control)
  └─ 滑动窗口(Sliding Window)
        │
拥塞控制(Congestion Control)
  └─ 慢启动 → 拥塞避免 → 快速恢复

UDP 的核心特性

1
2
3
4
5
6
7
8
9
10
11
12
13
无连接(Connectionless)
  └─ 无需握手,直接发送

不可靠传输(Unreliable)
  ├─ 无 ACK
  ├─ 无重传
  └─ 无序号(可能乱序)

无流量控制
  └─ 发送方无限制,接收方缓冲区满则丢包

低开销
  └─ 仅 8 字节头部(vs TCP 最小 20 字节)

最小示例

1
2
3
4
5
6
7
8
9
// WebSocket 基于 TCP(浏览器自动处理连接)
const ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = () => console.log('TCP 连接已建立');
ws.onmessage = (e) => console.log(e.data);
ws.send('hello');

// WebRTC 基于 UDP(需要 ICE/STUN/TURN 处理NAT穿透)
// 语音/视频通话不走 TCP(延迟太大)
// 直播平台推流:RTMP over TCP → HLS/DASH over HTTP → QUIC/UDP

核心知识点拆解

知识点 1:TCP 三次握手(连接建立)

1
2
3
4
5
6
7
8
9
10
11
12
13
客户端                                    服务器
  │                                          │
  │────── SYN=1, seq=x ────────────────────→│  第一次握手
  │         "我想建立连接,我的起始序号是 x"   │
  │                                          │
  │←──── SYN=1, ACK=1, seq=y, ack=x+1 ─────│  第二次握手
  │         "收到!我也准备好了,我的序号是 y,"
  │          "确认收到 x+1 之前的字节"
  │                                          │
  │────── ACK=1, seq=x+1, ack=y+1 ─────────→│  第三次握手
  │         "收到确认,建立完成!"
  │                                          │
  │           🟢 TCP 连接建立成功             │

为什么需要三次?

1
2
3
4
5
6
7
8
9
如果是两次握手:
客户端 ──── SYN ────────────────────────→ 服务器
           (SYN 丢了,客户端不知道,服务器以为连接建立了)
           (服务器开始分配资源,客户端永远不会发数据 → 浪费)

三次握手的本质:
  客户端确认:自己能发 + 服务器能收 ✅
  服务器确认:自己能发 + 客户端能收 ✅
  必须三次,两次不够,四次浪费

💡 对前端的影响:每次 HTTP/1.1 的新连接都需要三次握手 ≈ 增加 1-3 个 RTT(30-200ms)。HTTP/2 和 WebSocket 可以复用连接避免重复握手。

知识点 2:TCP 四次挥手(连接关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
客户端                                    服务器
  │                                          │
  │────── FIN=1, seq=u ────────────────────→│  第一次挥手
  │         "我发完了,想关闭我的写通道"        │
  │                                          │
  │←──── ACK=1, ack=u+1 ────────────────────│  第二次挥手
  │         "收到,但我可能还有数据要发"        │
  │         (服务器继续发送剩余数据)          │
  │                                          │
  │←──── FIN=1, seq=w ────────────────────│  第三次挥手
  │         "我也发完了,关闭我的写通道"        │
  │                                          │
  │────── ACK=1, ack=w+1 ──────────────────→│  第四次挥手
  │         "收到,连接正式关闭"              │
  │
  │         客户端等待 2MSL 后释放资源        │
  │              (防止最后的 ACK 丢失)       │

为什么挥手需要四次,但握手只需要三次?

1
2
3
4
握手:双方同时开始建立连接(SYN + SYN-ACK + ACK)
挥手:双方分别关闭自己的写通道(FIN + ACK + FIN + ACK)
      服务器收到第一次 FIN 后,可能还有数据要发 → 先回 ACK
      发完数据后才发 FIN → 多了这步导致四次

💡 对前端的影响:关闭 WebSocket 连接时,如果服务器不主动 close,客户端的 FIN 会等很久才收到响应。

知识点 3:TCP 拥塞控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
慢启动(Slow Start):
  cwnd(拥塞窗口)从 1 个 MSS 开始
  每收到一个 ACK,cwnd += 1 MSS
  → 指数增长,直到达到慢启动阈值(ssthresh)

拥塞避免(Congestion Avoidance):
  cwnd 达到阈值后,改为线性增长
  每 RTT,cwnd += 1 MSS

快速重传(Fast Retransmit):
  收到 3 个重复 ACK → 立即重传丢失的包
  → cwnd 减半,进入快速恢复

快速恢复(Fast Recovery):
  重传完成后,回到拥塞避免阶段

知识点 4:HTTP/WebSocket/QUIC 各用什么协议?

应用传输层理由
HTTP/1.1TCP需要可靠的请求-响应
HTTP/2TCP多路复用需要有序帧传输
HTTP/3QUIC (UDP)解决 TCP 队头阻塞,基于 UDP 自建可靠传输
WebSocketTCP双向流需要可靠传输
WebRTCUDP实时音视频不需要等待重传
DNS (通常)UDP速度快,不需要严格可靠(也有 TCP fallback)
QUICUDPHTTP/3 的底层协议

实战案例

案例一:WebSocket 连接的生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class WebSocketConnection {
  constructor(url) {
    this.ws = new WebSocket(url);
    this.ws.onopen = this.onOpen.bind(this);
    this.ws.onclose = this.onClose.bind(this);
    this.ws.onerror = this.onError.bind(this);
    this.ws.onmessage = this.onMessage.bind(this);
  }

  onOpen() {
    console.log('🟢 WebSocket 连接建立(底层:TCP 三次握手已完成)');
    // 发送心跳
    this.heartbeat = setInterval(() => {
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify({ type: 'ping' }));
      }
    }, 30000);
  }

  onClose(event) {
    console.log(`🔴 连接关闭(code: ${event.code})`);
    // WebSocket Close Code:
    // 1000 = 正常关闭
    // 1001 = 服务器关闭
    // 1006 = 连接异常断开(网络问题)
    clearInterval(this.heartbeat);
    // 自动重连策略
    setTimeout(() => this.reconnect(), 1000);
  }

  onError(error) {
    console.error('⚠️ WebSocket 错误:', error);
    // 底层可能是 TCP 连接失败或 TLS 握手失败
  }

  reconnect() {
    console.log('尝试重新连接...');
    // 实现指数退避重连
  }
}

案例二:理解 QUIC/UDP 在现代 Web 中的角色

1
2
3
4
5
6
7
8
HTTP/1.1 → TCP (3次握手 + TLS 握手 ≈ 2-3 RTT)
HTTP/2   → TCP (TLS 1.3 合并握手 ≈ 1 RTT)
HTTP/3   → QUIC/UDP (0-RTT 建立连接!)

HTTP/3 的 0-RTT 优势:
用户首次访问:需要 1 RTT(TLS 认证)
用户再次访问:0 RTT!直接发送加密数据
(基于之前会话的密钥恢复)

底层原理

TCP 滑动窗口(Flow Control)

1
2
3
4
5
6
7
8
9
10
11
发送方窗口(已发送未确认 | 未发送可发 | 不能发)
     ↓           ↓              ↓
[ 已发送-未确认  ][  已发送-未确认  ][ 未发送 ]
←────────── 接收方窗口大小 ──────────→

ACK 收到后,窗口向右滑动
如果接收方缓冲区满了:
  → 窗口大小变为 0
  → 发送方停止发送(Zero Window)
  → 接收方腾出空间后发送 Window Update
  → 发送方恢复发送

高频面试题解析

Q1:TCP 的三次握手和四次挥手是什么?

参考答案: 三次握手:SYN → SYN-ACK → ACK。目的是验证双方都能正常收发。 四次挥手:FIN → ACK → FIN → ACK。目的是确保双方都发完了数据。

Q2:TCP 和 UDP 的核心区别?

参考答案:

特性TCPUDP
连接性面向连接无连接
可靠性可靠传输不可靠
有序性有序无序
流量控制有滑动窗口
拥塞控制
头部开销20-60 字节8 字节
速度较慢(三次握手+重传)快速(无握手)
使用场景HTTP, WebSocket, 文件传输DNS, 直播, 游戏

Q3:HTTP/3 为什么改用 UDP(QUIC)?

参考答案: TCP 存在传输层队头阻塞:如果一个 TCP 包丢失,所有 HTTP 流都要等这个包重传完成才能继续。QUIC 基于 UDP 自己实现可靠传输,但将拥塞控制放在流级别而非连接级别——所以一个流丢包只影响那个流,其他流不受影响。

Q4:DNS 用 TCP 还是 UDP?

参考答案: 主要是 UDP(端口 53),速度快。但有三种情况会切换到 TCP:

  1. 响应数据超过 512 字节(DNS 响应截断)
  2. DNS 区域传输(AXFR)
  3. 客户端发起 TCP 探测失败后的 fallback

总结与扩展

核心要点

  1. TCP = 可靠 + 有序 + 流量控制 + 拥塞控制(用于 HTTP/WebSocket)
  2. UDP = 快速 + 无连接(用于 DNS/直播/QUIC)
  3. 三次握手 = SYN + SYN-ACK + ACK,验证双方收发能力
  4. 四次挥手 = FIN + ACK + FIN + ACK,确保数据发完再关
  5. HTTP/3 基于 QUIC/UDP,解决了 TCP 队头阻塞

延伸学习方向

  • QUIC 协议详解:0-RTT、重传机制、连接迁移
  • WebRTC 架构:ICE + STUN + TURN + DTLS + SRTP
  • HTTP/3:QUIC 的完整实现
  • TCP BBR 拥塞控制算法:Google 的新拥塞控制算法

相关主题

本文由作者按照 CC BY 4.0 进行授权

© 独行的风. 保留部分权利。

本站采用 Jekyll 主题 Chirpy

本站总访问量 本站访客数 本文阅读量