Network
1. HTTP/HTTPS
HTTP/1.1、2.0、3.0 的核心差异、进步点及尚未解决的缺陷(含队头阻塞问题)。
HTTP 的演进本质上是一场与延迟 (Latency) 和阻塞 (Blocking) 的战争。

- 1.1 的队头阻塞与应对:当时主要靠「域名分片」(开多个子域名)和「管道化」(效果不好,默认关闭)。
- 2.0 的缺陷:虽然在一条 TCP 通道里可以发多个请求,但如果其中一个数据包丢了,TCP 会为保证顺序性而停止后续所有包的处理,这就是 TCP 层的队头阻塞。
- 3.0 的改进:直接把底层换成 UDP。UDP 不管顺序,由上层的 QUIC 协议处理。流 A 丢包了,流 B 照样传输,互不干扰。
1.1 HTTPS 与 HTTP 的区别
HTTP 是明文传输,HTTPS 是加密传输(SSL/TLS)。HTTPS 解决三个问题:机密性(防窃听)、完整性(防篡改)、身份认证(防冒充)。
- 公钥的作用:非对称加密里的「锁」。任何人都可以用公钥加密,但只有持有私钥的服务器能解密。
- 证书的作用:公钥的「身份证」,防止攻击者替换成自己的公钥。证书由权威 CA 签名,证明「这个公钥确实属于该网站」。
1.2 TLS 握手过程(对称与非对称的配合)
HTTPS 并非全程非对称加密,而是混合加密:先用非对称加密「交换」密钥,再用对称加密「传输」数据。
- Client Hello:客户端发送支持的协议版本、随机数 R₁ 和加密套件列表。
- Server Hello:服务器确认协议版本,发送随机数 R₂ 和数字证书。
- 验证证书:客户端用浏览器内置的 CA 根证书验证证书有效性。
- 预主密钥 (Pre-master secret):客户端生成随机数 R₃,用证书中的服务器公钥加密后发给服务器。
- 生成对话密钥:双方用 R₁、R₂、R₃ 计算出相同的对称密钥。
- 加密交互:后续数据均用该对称密钥加密传输。
为何这样设计? 非对称加密计算量大、速度慢;对称加密快,但密钥传输不安全。两者结合,兼顾安全与性能。
1.3 中间人攻击与抓包
中间人攻击 (MITM):攻击者拦截、冒充,使自己处于通信双方之间。
日常抓包(如 Charles)原理:
- Charles 在电脑/手机上安装自家根证书。
- 访问 HTTPS 网站时,Charles 截获服务器发来的真实证书。
- Charles 伪造该网站的证书发给你(因你信任其根证书,浏览器不报错)。
- 你的数据先被 Charles 公钥加密,Charles 用私钥解密查看(抓包成功),再用真实服务器公钥加密转发给服务器。
总结:抓包工具本质是「经你授权的合法中间人」。
1.4 前端工程实践
雪碧图 (Sprites) 还有必要吗?
- HTTP/1.1 时代:很有必要,用于减少 HTTP 请求次数(每次连接都要握手,开销大)。
- HTTP/2 时代:基本没必要。多路复用使请求成本很低。过大的雪碧图反而带来:① 缓存利用率低(改一张小图整图失效);② 内存压力大。
- 建议:小图标改用 SVG 或 Icon Font。
301 vs 302
- 301 (Permanent Redirect):永久重定向。搜索引擎将旧 URL 权重转移到新 URL,浏览器会强缓存该结果。
- 302 (Found / Temporary Redirect):临时重定向。搜索引擎不转移权重,浏览器每次都会再请求旧地址。常用于未登录跳转登录页。
2. TCP/UDP
2.1 从输入 URL 到页面显示的完整闭环
- DNS 解析:域名 → IP(浏览器缓存 → 系统缓存 → 路由器缓存 → ISP DNS → 根域名服务器)。
- 建立连接:TCP 三次握手。
- 安全加密:TLS 握手(若为 HTTPS)。
- 发送请求:浏览器构建 HTTP 请求报文。
- 服务器处理:接收请求,返回 HTML 响应。
- 浏览器渲染:解析 HTML 建 DOM → 解析 CSS 建 CSSOM → 合并为 Render Tree → 布局 (Layout) → 绘制 (Painting)。
2.2 为什么是「三次」握手?
-
核心目的:确认双方收发能力正常,并同步初始化序列号 (ISN)。
-
通俗理解:
- A:你能听到我吗?(A 能发、B 能收)
- B:能,你能听到我吗?(B 能发、A 能收)
- A:能。
-
若只有两次:A 的 SYN 若在网络中滞留后才到达 B,B 会当作新连接建立并一直等数据,而 A 可能早已关闭,导致 B 资源浪费。
2.3 为什么是「四次」挥手?
- 原因:TCP 是全双工的。
- 逻辑:客户端说「我发完了」(FIN),服务器可能还有数据要发。服务器先回 ACK,等自己发完再发 FIN,最后客户端再发 ACK 确认。
2.4 异常与边界:最后一次 ACK 丢失
若客户端发出的第三次 ACK 丢失:
- 服务端:未收到确认,处于 SYN_RECV,会认为 SYN-ACK 丢了,启动指数退避重传(1s、2s、4s…),直到最大重传次数后关闭连接。
- 客户端:发完 ACK 后已进入 ESTABLISHED。
- 实际结果:若客户端随后发送数据,数据包中会带 ACK,服务端收到后可直接进入 ESTABLISHED;若客户端一直不发数据,服务端最终超时并发送 RST 强制断开。
2.5 可靠性保障(重传、拥塞控制等)
除握手机制外,TCP 在弱网下还依赖:
-
序列号与确认应答:每个包有编号,未收到则重传。
-
流量控制(滑动窗口):防止发送过快淹没接收端。
-
拥塞控制:
- 慢启动:起步发得少,窗口倍增,探测网络容量。
- 拥塞避免:达到阈值后线性增长。
- 快速重传:收到 3 个重复 ACK 即重传丢失包,不等超时,提高效率。
-
SACK(选择性确认):告知发送端具体丢失的包,避免重传其后所有包。
2.6 QUIC 与基于 UDP 的可靠传输
QUIC 如何实现可靠传输?
- Packet Number 单调递增:解决 TCP 重传歧义(原包与重传包区分不清)。
- 基于流 (Stream) 的传输:一个流阻塞不影响其他流。
- 连接迁移:TCP 用四元组(源 IP、源端口、目的 IP、目的端口)标识连接;QUIC 用 Connection ID。从 Wi-Fi 切到 5G(IP 变了)连接仍可保持。
若设计一套基于 UDP 的可靠协议 (如 RUDP),至少需要:
- 分片与组装:UDP 有长度限制,需给分片加序号 (Sequence Number)。
- 确认机制:ACK,告知发送方哪些已收到。
- 超时重传:记录每个包的发送时间,未收到 ACK 则重发。
- 重排缓冲区:UDP 乱序,接收端按序号重排后再交给应用层。
- 心跳检测:判断对端是否存活。
3. WebSocket
3.1 WebSocket 与 HTTP 的关系
A. HTTP/1.1 时代:协议升级 (Upgrade)
WebSocket 通过 HTTP 升级「借壳」建立。
- 握手:客户端发送带
Upgrade: websocket的 HTTP 请求。 - 切换:服务器返回 101 Switching Protocols。
- 接管:此后该 TCP 连接由 WebSocket 完全接管,后续为 WebSocket 定义的二进制帧。
B. HTTP/2 时代:流内隧道 (Extended CONNECT, RFC 8441)
HTTP/2 已是二进制且多路复用,WebSocket 不必再「替换」整条连接。
- 机制:WebSocket 跑在 HTTP/2 的某个 Stream 里。
- 不再用 101:通过 CONNECT 方法建立隧道,无需协议切换状态码。
- 共存:同一 TCP 连接上,Stream 1 可传普通 HTTP/2 资源,Stream 3 传 WebSocket(WS 帧装在 HTTP/2 DATA 帧里)。
- 区分:HTTP/2 帧负责「封装与路由」,WebSocket 帧负责「业务数据」。
3.2 长连接实践要点
长连接要避免「假死」和「雪崩」。
-
心跳 (Heartbeat)
- 在应用层做 Ping/Pong,不要只依赖 TCP Keep-Alive(太慢)。
- 例如每 30 秒一次;连续 3 次无响应则断开并重连。
-
断线重连与指数退避
- 不要一断线就立刻重连,易造成服务端瞬时压力。
- 建议:重试间隔 = min(2ⁿ + 随机抖动, 最大延迟)。加 Jitter 可避免大量客户端在同一时刻重连。
-
服务端状态同步(多机)
- 用户 A 在 Server 1,用户 B 在 Server 2,消息需跨机转发。
- 常见做法:用 Redis Pub/Sub。Server 1 把消息发到 Redis,Server 2 订阅后发现目标用户在本机,再推给 B。
3.3 长连接安全:校验与防护
长连接「一次握手、长期有效」,身份校验必须在建立时做牢。
-
握手阶段校验 (HTTP 阶段)
- JWT / Token:在 101 或 CONNECT 请求中,通过 Header 或 URL 参数携带。
- Cookie:浏览器环境下利用同源策略自动携带 Cookie 校验。
-
连接建立后校验
- 「首包」校验:建立后若干秒内(如 5 秒)必须收到带
auth_token的业务消息,否则服务端主动断开。
- 「首包」校验:建立后若干秒内(如 5 秒)必须收到带
-
传输安全 (WSS)
- 必须使用 wss://(WebSocket + TLS),防窃听与运营商注入。
-
防御 CSRF(跨站 WebSocket 劫持)
- 服务端必须校验 Origin。来自非预期站点的 WS 连接应直接拒绝。