Day 2 网络协议 — 面试备考手册
1. TCP 三次握手 / 四次挥手
三次握手(建立连接)
Client Server | ── SYN, seq=X ──▶ | 第一次:我想连你,我的序号是X | ◀─ SYN+ACK, seq=Y ─| 第二次:收到,我的序号是Y,确认你的X | ── ACK ──────────▶ | 第三次:收到,连接建立
为什么必须三次,不能两次?
两次握手后 Client 已经确认双向通信正常,但 Server 不知道自己的发送是否有效
第三次握手就是 Client 告诉 Server “你发的我收到了”。三次握手确保双方都能正常收发。
还有一个原因:防止网络中延迟的旧 SYN 包被误认为新连接请求,造成资源浪费。
四次挥手(断开连接)
Client Server | ── FIN ───────────▶ | 我发完了,想断开 | ◀─ ACK ─────────── | 收到,但我还有数据没发完 | ◀─ FIN ─────────── | 我也发完了 | ── ACK ───────────▶ | 好的,再见
为什么挥手要四次?
TCP 是全双工的,Client 和 Server 各自有一个发送通道,必须分别关闭。Server 收到 FIN 后可能还有数据没发完,所以 ACK 和 FIN 必须分开,不能合并成三次。
TIME_WAIT 状态: Client 发出最后的 ACK 后,要等 2×MSL(约 2 分钟)才真正关闭,防止最后的 ACK 丢失后 Server 重发 FIN 时无人响应。
2. HTTP vs HTTPS / TLS 握手 / 证书链
HTTP vs HTTPS
HTTP 是明文传输,没有加密、没有身份验证。HTTPS = HTTP + TLS,解决了三个问题:
- 加密:传输内容不被窃听
- 认证:确认你访问的是真正的服务器
- 完整性:内容没被篡改
TLS 握手过程(面试只需记住这个流程)
Client Server | ── Client Hello ─────────▶ | 发送:支持的加密算法、随机数A | ◀─ Server Hello ────────── | 回复:选择的加密算法、随机数B、数字证书 | 验证证书(证书链) | | ── Pre-Master Secret ─────▶| 用服务器公钥加密后发送 | 双方各自生成对称密钥 | 用 随机数A + 随机数B + Pre-Master Secret 推导 | ◀══════ 加密通信开始 ══════▶ |
TLS 1.3 的改进: 握手从 2-RTT 缩短到 1-RTT,重连可以 0-RTT,废弃了老旧不安全的加密套件。
证书链
Root CA(根证书,浏览器内置信任)
└── Intermediate CA(中间证书)
└── End Entity Certificate(你的网站证书)
验证过程:从网站证书往上逐级验签,直到找到浏览器内置信任的根证书。验证内容包括:有效期、域名是否匹配、签名是否正确。
3. DNS 解析全流程
用户输入 www.example.com,发生了什么:
1. 浏览器缓存 → 命中就返回 2. 操作系统缓存 / hosts 文件 → 命中就返回 3. 本地 DNS 解析器(路由器/ISP) → 缓存未命中,开始向外查询 4. → 根域名服务器:".com 的 TLD 服务器在哪?" 5. → .com TLD 服务器:"example.com 的权威 DNS 在哪?" 6. → example.com 权威 DNS:"www.example.com 的 IP 是什么?" 7. ← 返回 IP 地址,本地 DNS 缓存(按 TTL),返回给浏览器
关键概念:
- TTL:DNS 记录的缓存有效时间,越小更新越快但查询越频繁
- 迭代查询:本地 DNS 自己一步步问(上面的流程)
- 递归查询:浏览器问本地 DNS,本地 DNS 全权代劳
- DoH / DoT:DNS over HTTPS / TLS,防止 DNS 查询被监听篡改
4. HTTP/1.1 vs HTTP/2 vs HTTP/3
核心问题与演进
| 问题 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 并发请求 | 每域名 6 个 TCP 连接 | 单连接多路复用 | 单连接多路复用 |
| 队头阻塞 | 有(应用层) | 解决了应用层,TCP 层仍有 | 彻底解决 |
| Header | 每次完整发送,冗余大 | HPACK 压缩 | QPACK 压缩 |
| 传输格式 | 文本 | 二进制分帧 | 二进制 |
| 底层协议 | TCP | TCP | QUIC(基于 UDP) |
| 连接建立 | TCP + TLS 共 3-RTT | 同左 | 1-RTT,重连 0-RTT |
| 网络切换 | 断连 | 断连 | 不断连(Connection ID) |
记住一句话: HTTP/2 解决了应用层的队头阻塞,但 TCP 丢包时整个连接都要等重传;HTTP/3 换成 QUIC(UDP),每个 stream 独立,丢包只影响那一个流。
5. REST vs gRPC
一句话区别
REST 是给人和浏览器用的,gRPC 是给服务和服务用的。
详细对比
| 维度 | REST | gRPC |
|---|---|---|
| 协议 | HTTP/1.1 或 HTTP/2 | HTTP/2 |
| 数据格式 | JSON(文本,可读) | Protocol Buffers(二进制,高效) |
| 类型安全 | 无强制约束 | .proto 文件定义,强类型 |
| 通信模式 | 请求-响应 | 支持双向流式通信 |
| 性能 | 中等 | 高(序列化快约 5-10 倍) |
| 浏览器支持 | 完美 | 有限(需要 grpc-web) |
| 调试 | 容易(curl/Postman) | 相对复杂 |
什么时候用 REST: 公开 API、需要浏览器直接访问、简单 CRUD、对外接口。
什么时候用 gRPC: 微服务之间内部调用、需要高吞吐低延迟、需要流式传输(如实时日志、视频流)、多语言系统(.proto 自动生成各语言代码)。
6. WebSocket vs Long Polling
三种”实时”方案对比
短轮询(Short Polling):
客户端每隔 N 秒问一次”有新消息吗?”。简单粗暴,浪费资源,不算实时。
长轮询(Long Polling):
Client ──请求──▶ Server(挂起,等数据)
有数据了!
Client ◀──响应── Server
Client ──立刻再请求──▶ Server(继续挂起)
比短轮询实时,但本质还是 HTTP 请求-响应,每次有消息都要重建连接,高并发时服务器连接数压力大。
WebSocket:
Client ──HTTP Upgrade──▶ Server 一次握手升级 Client ◀══ 持久双向连接 ══▶ Server 之后随时互发消息
真正的全双工实时通信,服务器可以主动推送,延迟最低,适合聊天、游戏、实时数据面板。代价是需要服务器维护长连接状态,水平扩展需要处理连接路由问题(比如用 Redis Pub/Sub 做跨节点广播)。
选择原则:
- 只需服务器推送 → SSE(Server-Sent Events,更简单)
- 需要双向实时 → WebSocket
- 改造成本高、偶发推送 → Long Polling 也够用
高频追问备忘
- TCP 和 UDP 的区别? TCP 可靠有序,UDP 快但不保证到达,适合视频/游戏/DNS
- HTTPS 一定安全吗? 证书可以被伪造(中间人攻击),需要 HSTS + 证书透明度日志
- HTTP/2 的多路复用为什么解决不了 TCP 的队头阻塞? TCP 是字节流,丢一个包整个连接的所有 stream 都要等重传,HTTP/2 的 stream 只是应用层抽象
- gRPC 的四种通信模式? Unary(一请求一响应)、Server Streaming、Client Streaming、Bidirectional Streaming
