计算机网络原理
面试题里那 39 道「计算机网络」题,都建立在这篇的原理之上。 按「TCP/UDP → HTTP → HTTPS → DNS」四层往下读。
一、分层模型
OSI 七层 TCP/IP 四层 常见协议/设备
─────────────────────────────────────────────────────
应用层 应用层 HTTP / DNS / FTP
表示层 (编解码)
会话层 (会话管理)
─────────────────────────────────────────────────────
传输层 传输层 TCP / UDP
─────────────────────────────────────────────────────
网络层 网络层 IP / ICMP / ARP
─────────────────────────────────────────────────────
数据链路层 网络接口层 以太网 / 交换机
物理层 (网线/光/集线器)OSI 七层 TCP/IP 四层 常见协议/设备
─────────────────────────────────────────────────────
应用层 应用层 HTTP / DNS / FTP
表示层 (编解码)
会话层 (会话管理)
─────────────────────────────────────────────────────
传输层 传输层 TCP / UDP
─────────────────────────────────────────────────────
网络层 网络层 IP / ICMP / ARP
─────────────────────────────────────────────────────
数据链路层 网络接口层 以太网 / 交换机
物理层 (网线/光/集线器)为什么分层:每一层只关心自己的职责,向上提供服务、向下屏蔽差异。应用层不用知道底下是 WiFi 还是光纤。
二、TCP 与 UDP
| TCP | UDP | |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(确认 + 重传) | 尽力而为,可能丢 |
| 顺序 | 有序 | 无序 |
| 头部 | 20 字节起 | 8 字节 |
| 场景 | HTTP、文件、数据库 | 视频、语音、DNS、游戏 |
三次握手与四次挥手
三次握手(建立连接)
客户端 ──SYN seq=x──────→ 服务端
客户端 ←─SYN+ACK x+1,y─── 服务端
客户端 ──ACK y+1────────→ 服务端
四次挥手(释放连接,为什么比握手多一次?)
主动方 ──FIN────────────→ 被动方
主动方 ←─ACK──────────── 被动方 (半关闭:被动方可能还有数据要发)
主动方 ←─FIN──────────── 被动方
主动方 ──ACK────────────→ 被动方三次握手(建立连接)
客户端 ──SYN seq=x──────→ 服务端
客户端 ←─SYN+ACK x+1,y─── 服务端
客户端 ──ACK y+1────────→ 服务端
四次挥手(释放连接,为什么比握手多一次?)
主动方 ──FIN────────────→ 被动方
主动方 ←─ACK──────────── 被动方 (半关闭:被动方可能还有数据要发)
主动方 ←─FIN──────────── 被动方
主动方 ──ACK────────────→ 被动方两个必背结论:
- 握手是三次:因为「两次」只能证明客户端能到服务端,无法证明服务端能到客户端(防止已失效的连接请求突然又传到了服务端)。
- 挥手是四次:TCP 是全双工的,关闭要两个方向各关一次;其中
FIN和ACK可以合并,所以至少三次、通常四次。
可靠传输三件套
| 机制 | 作用 |
|---|---|
| 确认 + 超时重传 | 收不到 ACK 就重发 |
| 滑动窗口 | 一次可发多个包(流量控制 + 提升吞吐) |
| 拥塞控制 | 慢启动、拥塞避免、快重传、快恢复(感知网络拥塞,别把网压垮) |
TIME_WAIT 与常见问题
- TIME_WAIT:主动关闭方在发送最后一个 ACK 后,要等 2MSL 才释放连接,防止旧连接的数据串到新连接、确保对方收到最后的 ACK。
- 粘包/拆包:TCP 是字节流没有边界,应用层要自己定界(长度字段 / 分隔符 / 定长)—— 实现见 Java NIO。
三、HTTP 演进
| 版本 | 关键变化 | 解决的问题 |
|---|---|---|
| HTTP/1.0 | 短连接 | 每次请求都要重连(慢) |
| HTTP/1.1 | 长连接(Keep-Alive)+ 管线化 | 复用连接;但队头阻塞仍在 |
| HTTP/2 | 二进制分帧 + 多路复用 + 头部压缩(HPACK) | 一个连接并发多请求,队头阻塞解决 |
| HTTP/3 | 基于 QUIC(UDP) | 丢包不再阻塞其他流,握手更快 |
状态码(高频):
200成功、201创建、204无内容301永久重定向、302临时重定向、304未修改(走缓存)400参数错、401未认证、403无权限、404不存在、429限流500服务器内部错、502网关坏、503过载、504网关超时
Cookie / Session / Token
| 存储 | 问题 | |
|---|---|---|
| Cookie | 客户端,随请求自动带 | 有 CSRF 风险 |
| Session | 服务端,Cookie 存 id | 横向扩展要共享 session |
| Token(JWT) | 客户端,请求头带 | 无法主动失效,要短 TTL + 刷新 |
四、HTTPS 与 TLS
HTTPS = HTTP + TLS(在 TCP 之上、HTTP 之下的一层加密)HTTPS = HTTP + TLS(在 TCP 之上、HTTP 之下的一层加密)为什么是「混合加密」
| 阶段 | 用什么 | 为什么 |
|---|---|---|
| 握手期(协商会话密钥) | 非对称加密(RSA/ECDHE) | 安全地交换密钥 |
| 数据传输期 | 对称加密(AES) | 快 |
TLS 握手(简化)
客户端 → ClientHello(支持的版本、加密套件、随机数)
服务端 → ServerHello + 证书 + ServerKeyExchange
客户端 → 验证证书 → 生成预主密钥 → 用服务端公钥加密发送
双方 → 用「随机数 + 预主密钥」导出会话密钥 → 之后对称加密客户端 → ClientHello(支持的版本、加密套件、随机数)
服务端 → ServerHello + 证书 + ServerKeyExchange
客户端 → 验证证书 → 生成预主密钥 → 用服务端公钥加密发送
双方 → 用「随机数 + 预主密钥」导出会话密钥 → 之后对称加密证书链:浏览器用内置的 CA 根证书,逐级验证服务器证书的可信性,确认「这个公钥确实是这个域名的」。
五、DNS 解析
浏览器输入域名 → 查浏览器缓存 → 查 hosts → 查本地 DNS 缓存
→ 递归查询 DNS 服务器 → 根域 → 顶级域(.com) → 权威域 → 得到 IP浏览器输入域名 → 查浏览器缓存 → 查 hosts → 查本地 DNS 缓存
→ 递归查询 DNS 服务器 → 根域 → 顶级域(.com) → 权威域 → 得到 IPCDN 的原理:域名解析到「离用户最近的边缘节点」,边缘节点回源站取数据并缓存。
六、跨域与代理
- 跨域:浏览器的同源策略(协议 + 域名 + 端口一致)。解法:CORS(服务端加响应头)、JSONP(只支持 GET,已过时)、反向代理(开发环境最常用)。
- 正向代理 / 反向代理:正向代理代理客户端(翻墙);反向代理代理服务端(Nginx 站在服务器前面)。
七、速查
| 问题 | 一句话 |
|---|---|
| 三次握手为什么是三次 | 防止失效连接请求,确认双方收发都通 |
| 四次挥手为什么比握手多 | 全双工,两方向各关一次 |
| TCP 怎么保证可靠 | 确认 + 重传 + 滑动窗口 + 拥塞控制 |
| HTTP/2 最大改进 | 多路复用,解决队头阻塞 |
| HTTPS 用什么加密 | 握手用非对称,传输用对称 |
| 粘包怎么解决 | 应用层定界:长度字段 / 分隔符 / 定长 |
| 跨域怎么解决 | CORS 响应头,或反向代理 |
| CDN 原理 | 就近解析 + 边缘缓存 |
Cao Note