- Published on
网络
- Authors
- Name
- Reeswell
概述
网络通信是现代计算机系统交互的核心,理解其分层模型、数据传输过程以及安全策略(如同源策略)对前端、后端和全栈开发都至关重要。
5层网络模型详解(OSI简化版)
1. 物理层(Physical Layer)
- 功能:负责比特流的物理传输,例如通过网线、光纤、无线电波等介质传输0和1
- 设备:网卡、集线器
- 关键概念:曼彻斯特编码、调制解调、带宽、速率
2. 数据链路层(Data Link Layer)
- 功能:将比特组织成帧(Frame),提供相邻节点之间的可靠传输,处理MAC地址寻址和差错控制
- 协议:Ethernet、PPP
- 核心功能:
- 帧同步
- 流量控制
- 差错检测(CRC校验)
- MAC寻址
- 示例:局域网内主机A通过MAC地址找到主机B
3. 网络层(Network Layer)
- 功能:负责将数据包从源主机发送到目标主机,跨越多个网络
- 核心协议:IP(IPv4/IPv6)
- 主要功能:
- 逻辑寻址(IP地址)
- 路由选择(路由器转发)
- 分片与重组
- 协议:IP、ICMP、ARP(用于IP到MAC的映射)
- 数据单位:数据报(Datagram)或分组(Packet)
4. 传输层(Transport Layer)
- 功能:提供端到端的通信服务,确保数据可靠、有序传输
主要协议
TCP(Transmission Control Protocol)
- 面向连接、可靠、基于字节流
- 适用于HTTP、FTP等
- 特性:
- 三次握手
- 四次挥手
- 滑动窗口
- 拥塞控制
- 确认重传机制
UDP(User Datagram Protocol)
- 无连接、不可靠、速度快
- 适用于视频流、DNS查询
注意:端口号用于区分同一主机上的不同应用进程(如80为HTTP,443为HTTPS)
5. 应用层(Application Layer)
- 功能:直接为用户应用提供服务,定义应用间通信的协议
- 常见协议:HTTP、HTTPS、DNS、SMTP、FTP
- 数据单位:消息(Message)
数据传输过程
封装与解封装机制
数据在发送时自上而下封装,接收时自下而上解封装:
应用层消息 → 传输层加TCP头 → 网络层加IP头 → 数据链路层加帧头/尾 → 物理层比特流
每一层只关心自己的头部信息,形成"封装-解封装"机制。
HTTP请求发送过程详解
以浏览器访问 www.example.com
为例:
步骤1:URL解析
- 协议:https
- 域名:www.example.com
- 端口:443(默认)
步骤2:DNS解析(应用层)
浏览器检查缓存 → 系统缓存 → 路由器 → ISP DNS服务器 → 根DNS → 顶级域 → 权威DNS
最终获取IP地址,如 93.184.216.34
步骤3:建立TCP连接(传输层)
客户端发起三次握手:
- SYN(seq=x)
- SYN-ACK(seq=y, ack=x+1)
- ACK(seq=x+1, ack=y+1)
连接建立成功,进入 ESTABLISHED
状态。
步骤4:TLS握手(若为HTTPS)
客户端发送ClientHello → 服务端回应ServerHello、证书、公钥 → 客户端验证证书、生成会话密钥并加密发送 → 双方协商出对称加密密钥,后续通信加密
步骤5:发送HTTP请求(应用层)
请求报文示例:
GET /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive
...
步骤6:网络层与数据链路层处理
应用层数据 → TCP段(加端口、序列号等)
TCP段 → IP数据报(加源IP、目的IP、TTL等)
IP数据报 → 以太网帧(加源MAC、目的MAC)
帧 → 比特流通过物理介质传输
路由器根据IP地址逐跳转发,交换机根据MAC地址转发。
步骤7:服务器响应
服务器返回HTTP响应(状态码、响应头、响应体),客户端接收后渲染页面。
步骤8:连接关闭(可选)
四次挥手释放TCP连接。
同源策略(Same-Origin Policy)
定义
两个URL的协议(scheme)、主机名(host)、**端口(port)**完全相同时,才被认为是同源。
示例
URL1 | URL2 | 是否同源 | 原因 |
---|---|---|---|
http://a.com:8080 | http://a.com:80 | ❌ | 端口不同 |
https://a.com | http://a.com | ❌ | 协议不同 |
a.com | b.a.com | ❌ | 子域不同 |
注意:主域名相同但子域不同时,除非显式设置
document.domain
,否则非同源
作用
防止恶意脚本读取其他站点的敏感数据(如Cookie、DOM),是Web安全基石之一。
限制范围
- XMLHttpRequest / Fetch API 请求
- DOM访问(iframe间)
- Cookie、LocalStorage访问(受限)
跨域问题(Cross-Origin Resource Sharing, CORS)
成因
浏览器出于安全考虑,阻止前端JavaScript发起跨域请求或读取响应。
常见场景
- 前端运行在
http://localhost:3000
,后端API在http://api.example.com:8080
- 静态资源托管在CDN,但接口在另一域名
解决方案
1. CORS(跨域资源共享)——推荐方式
服务端设置响应头:
Access-Control-Allow-Origin: https://example.com 或 *
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true(需配合withCredentials)
请求类型:
- 简单请求(Simple Request):满足条件(如GET/POST + 安全头)直接发送
- 预检请求(Preflight Request):非简单请求先发OPTIONS请求询问是否允许
Node.js Express 示例:
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://example.com')
res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE')
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
if (req.method === 'OPTIONS') {
res.sendStatus(200)
} else {
next()
}
})
2. 代理服务器(Proxy)
开发环境常用:Webpack DevServer、Vite、Nginx反向代理
原理:前端请求本地服务器,本地服务器转发请求到目标API,绕过浏览器同源限制
Nginx配置示例:
location /api/ {
proxy_pass http://backend-server/api/;
}
3. JSONP(JSON with Padding)——仅支持GET
利用 <script>
标签不受同源策略限制的特性,通过动态创建script标签实现跨域请求。
总结
理解网络模型和跨域机制对于现代Web开发至关重要:
- 5层网络模型提供了清晰的分层架构,每层都有明确的职责
- HTTP请求过程涉及DNS解析、TCP连接、数据传输等多个步骤
- 同源策略是浏览器安全的基础,但也会带来跨域问题
- CORS是解决跨域问题的标准方案,需要前后端配合
掌握这些知识有助于更好地理解网络通信原理,解决实际开发中的问题。
浏览器相关
从输入 URL 到页面渲染的流程
输入 URL 之后,浏览器会经历一系列复杂的步骤,包括 URL 解析、DNS 查询、建立 TCP 连接、发送 HTTP 请求、服务器处理并返回响应、浏览器解析渲染页面、以及可能的 HTTPS 安全握手等过程。
主要流程
- URL 解析:用户在浏览器地址栏输入 URL(统一资源定位符)
- URL 解析:浏览器对 URL 进行解析,提取出协议、主机名、端口、路径等信息
- DNS 查询:通过 DNS(域名系统)将域名解析为对应的 IP 地址
- 建立 TCP 连接:建立与目标服务器的 TCP 连接(通常使用三次握手)
- TLS/SSL 握手:若使用 HTTPS,则还需进行 TLS/SSL 握手以加密通信
- 发送 HTTP 请求:浏览器构造 HTTP 请求报文并发送给服务器
- 服务器处理:服务器接收请求,处理后返回 HTTP 响应(如 HTML 文档)
- 页面渲染:浏览器接收响应数据,开始解析 HTML、构建 DOM 树、CSSOM 树、执行 JavaScript、布局与渲染页面
- 资源加载:同时加载页面中的子资源(如图片、CSS、JS 文件),重复类似流程
- 完成渲染:最终完成页面展示,并保持连接可选(HTTP 持久连接)或关闭连接
详细技术解析
URL 解析
URL 结构:协议://用户名:密码@主机名:端口/路径?查询参数#片段标识符
示例:https://www.example.com:8080/path/page.html?name=value#section
浏览器从中提取关键信息用于后续流程,如协议决定是否加密(HTTP vs HTTPS),主机名用于 DNS 查询。
DNS 查询过程(域名解析)
目标:将域名(如 www.example.com
)转换为 IP 地址(如 93.184.216.34
)
查询步骤:
- 浏览器缓存查询
- 操作系统缓存查询
- 路由器 DNS 缓存
- ISP(互联网服务提供商)的 DNS 服务器
- 递归查询:若未命中,发起递归查询,根域名服务器 → 顶级域(.com) → 权威域名服务器
技术细节:
- 使用 UDP 协议,默认端口 53
- 可能使用 DNS over HTTPS(DoH)或 DNS over TLS(DoT)增强隐私
TCP 三次握手(Transmission Control Protocol)
握手过程:
- 客户端发送 SYN(同步序列编号)
- 服务器回应 SYN-ACK
- 客户端发送 ACK 确认
- 完成连接建立,进入 ESTABLISHED 状态
核心原理:
- 确保双向通信可靠,基于序列号和确认机制
- 三次握手防止历史连接请求造成资源浪费
TLS/SSL 握手(针对 HTTPS)
握手过程:
- 客户端发送 ClientHello(支持的协议版本、加密套件)
- 服务器回应 ServerHello(选定协议和加密方式)、证书(含公钥)、可选请求客户端证书
- 客户端验证证书(CA 链、有效期、域名匹配)、生成预主密钥,用服务器公钥加密发送
- 双方基于预主密钥生成会话密钥
- 完成握手,后续通信使用对称加密(如 AES)
目标:实现身份认证、数据加密、完整性保护
HTTP 请求发送
请求构造:
- 构造请求行(如
GET /path HTTP/1.1
) - 添加请求头(Host, User-Agent, Accept, Cookie 等)
- 若为 POST,包含请求体(如表单数据)
- 通过已建立的 TCP 连接发送
服务器处理与响应
处理流程:
- Web 服务器(如 Nginx、Apache)接收请求
- 根据路径路由到后端应用(如 Node.js、Java Spring)
- 应用处理逻辑(数据库查询、业务计算)
- 生成响应(如 HTML 页面)
- 返回 HTTP 响应报文:状态码(200 OK)、响应头(Content-Type, Set-Cookie)、响应体
浏览器解析与渲染(Rendering Pipeline)
渲染流程:
- HTML 解析:接收 HTML 字节流,进行字节 → 字符 → 令牌 → 节点 → DOM 树构建
- CSS 解析:遇到 CSS 资源,下载并解析生成 CSSOM(CSS 对象模型)
- 构建渲染树:合并 DOM + CSSOM → Render Tree(渲染树)
- 布局(Layout / Reflow):计算每个元素的几何位置
- 绘制(Paint):将像素信息绘制到图层
- 合成(Composite):多个图层合并成最终画面
- JavaScript 执行:可能修改 DOM/CSSOM,触发重排或重绘
子资源加载
加载过程:
- 解析 HTML 过程中发现
img
、link
、script
标签 - 对每个资源发起新的 HTTP 请求(可能并行,受限于浏览器并发限制,如 Chrome 约 6 个)
- JavaScript 默认阻塞 HTML 解析(除非加
async
或defer
) - CSS 阻塞渲染(render-blocking)
defer和async有哪些区别?
正确答案
<script>
标签的优化方式包括:
- 使用
defer
和async
属性 - 将脚本放在页面底部
- 减少脚本数量
- 延迟加载非关键 JS
其中,defer 和 async 的区别如下:
- defer:脚本异步加载,按 HTML 中出现的顺序执行,并且会在文档解析完成后统一执行。
- async:脚本异步加载,下载完成后立即执行,执行时仍阻塞解析,不保证执行顺序。
它们主要影响页面的首次内容绘制(First Contentful Paint, FCP)和可交互时间(Time to Interactive, TTI)。defer
和 async
都能提升 FCP,因为不会阻塞 HTML 解析。
1、解答思路
- 浏览器渲染流程中,默认
<script>
标签会阻塞 HTML 解析直到脚本下载并执行完毕,导致“白屏”或延迟内容渲染。 - 使用
defer
和async
可以避免阻塞,适用于不同场景。 - 这两种属性通过减少阻塞时间提升 FCP。
2、深度知识讲解
script 标签的优化方式
- 放置位置:传统做法是将
<script>
放在</body>
之前,避免阻塞 HTML 解析。 - 合并与压缩:减少请求数量,使用构建工具压缩代码体积。
- 异步加载:使用
async
或defer
属性,让脚本异步加载。 - 懒加载非关键 JS:如使用动态
import()
按需加载模块。 - 利用 CDN 加速:缩短资源加载时间。
- 预加载提示:使用
<link rel="preload">
提前加载关键脚本。
defer vs async
特性 | defer | async |
---|---|---|
加载方式 | 异步加载 | 异步加载 |
执行时机 | 文档解析完成后统一执行 | 下载完成后立即执行 |
执行顺序 | 按 HTML 顺序执行 | 不保证顺序 |
是否阻塞解析 | 否 | 否 |
适合依赖 DOM | 是 | 否(可能 DOM 未构建) |
对性能指标的影响
- FCP(首次内容绘制):默认同步脚本会阻塞 HTML 解析,延迟首次渲染。使用
defer
或async
可避免阻塞,使内容更早被绘制。 - TTI(可交互时间):如果脚本包含大量逻辑或事件绑定,会影响 TTI。
async
脚本可能更快执行,但也可能更早触发 TTI;defer
通常在最后阶段执行,可能稍晚一些。 - CLS(累计布局偏移):如果 JS 操作布局或插入样式,可能导致布局偏移,影响 CLS。
3、实现原理(底层机制)
浏览器有两个独立的下载通道:
- 一个用于 HTML 解析器
- 一个用于预加载扫描器(Preload Scanner)
- 没有
async
或defer
的<script>
:HTML 解析器必须暂停,直到脚本下载并执行完毕(解析阻断)。 - 使用
defer
或async
时:- 预加载扫描器异步下载脚本
- 解析器继续解析 HTML
defer
脚本加入队列,等 HTML 解析完成后按顺序执行async
脚本下载完成后立即执行,不排队
http2
深度知识讲解:HTTP/2
1. HTTP/2 的背景
- HTTP/2 是 IETF 标准化的新一代 HTTP 协议(RFC 7540),起源于 Google 的 SPDY 协议。
- 主要目标:减少页面加载时间、提升性能,尤其在高延迟或高并发场景下表现更优。
2. HTTP/2 与 HTTPS 的关系
- 协议规范层面:RFC 7540 并未强制要求加密(TLS),理论上可用明文 HTTP/2(h2c, HTTP/2 Clear Text)。
- 现实部署层面:主流浏览器(如 Chrome、Firefox)出于安全考虑不支持明文 HTTP/2,只允许基于 TLS 的加密版本(h2)。
- 结论:现代 Web 实际上 HTTP/2 = HTTPS + HTTP/2。
3. 为什么要用 HTTP/2?
- 安全性:HTTPS 提供端到端加密,防止中间人攻击(MITM)。
- 多路复用:多个请求可在同一 TCP 连接上并行发送,极大减少延迟。
- 头部压缩:采用 HPACK 算法,显著减少请求/响应头部体积。
- 服务器推送:服务端可主动推送资源给客户端,提升首屏速度。
4. TLS 在 HTTP/2 中的作用
- 推荐使用 TLS 1.2 或更高版本(如 TLS 1.3)建立加密通道。
- ALPN(Application-Layer Protocol Negotiation) 扩展用于协商 HTTP/2 或 HTTP/1.1。
- 在 TLS 握手阶段,客户端和服务端通过 ALPN 交换支持的协议列表,最终选择 h2 作为应用层协议。
5. 实现原理简要流程
当客户端发起 HTTPS 请求时:
- 客户端发送
ClientHello
,包含支持的 TLS 版本、加密套件和 ALPN 列表(如h2
,http/1.1
)。 - 服务端响应
ServerHello
,选择h2
作为协议。 2. HTTP/2 与 HTTPS 的关系
- 客户端发送
协议规范层面:RFC 7540 并未强制要求加密(TLS),理论上可用明文 HTTP/2(h2c, HTTP/2 Clear Text)。
现实部署层面:主流浏览器(如 Chrome、Firefox)出于安全考虑不支持明文 HTTP/2,只允许基于 TLS 的加密版本(h2)。
结论:现代 Web 实际上 HTTP/2 = HTTPS + HTTP/2。
3. 为什么要用 HTTP/2?
- 安全性:HTTPS 提供端到端加密,防止中间人攻击(MITM)。
- 多路复用:多个请求可在同一 TCP 连接上并行发送,极大减少延迟。
- 头部压缩:采用 HPACK 算法,显著减少请求/响应头部体积。
- 服务器推送:服务端可主动推送资源给客户端,提升首屏速度。
4. TLS 在 HTTP/2 中的作用
- 推荐使用 TLS 1.2 或更高版本(如 TLS 1.3)建立加密通道。
- ALPN(Application-Layer Protocol Negotiation) 扩展用于协商 HTTP/2 或 HTTP/1.1。
- 在 TLS 握手阶段,客户端和服务端通过 ALPN 交换支持的协议列表,最终选择 h2 作为应用层协议。
5. 实现原理简要流程
当客户端发起 HTTPS 请求时:
- 客户端发送
ClientHello
,包含支持的 TLS 版本、加密套件和 ALPN 列表(如h2
,http/1.1
)。 - 服务端响应
ServerHello
,选择h2
作为协议。 - 后续通信使用 HTTP/2 的二进制帧格式进行数据传输。
- 客户端发送
6. 示例代码(伪代码)
扩展知识点
性能优化技术
- DNS 预解析:浏览器提前解析页面中可能出现的域名,提升性能
- 预连接(Preconnect):提前建立 TCP 和 TLS 连接
- 预加载(Preload):提示浏览器优先加载关键资源
Preload 与 Prefetch 的区别及使用场景
特性 | Preload(预加载) | Prefetch(预取) |
---|---|---|
用途 | 预加载当前页面即将用到的关键资源(如 JS、CSS、字体等) | 预加载未来可能用到的资源(如下一页脚本、路由组件等) |
加载时机 | 页面解析初期,优先级高,尽早加载 | 浏览器空闲时,优先级低,异步加载 |
加载保证 | 必须加载,浏览器会确保资源被获取 | 可能加载,浏览器可根据网络状况决定是否加载 |
典型用法 | <link rel="preload" href="critical.js" as="script"> | <link rel="prefetch" href="next-page.js"> |
适用场景 | 首屏关键 JS、字体、重要样式,减少渲染阻塞 | SPA 路由级预加载,提升页面切换速度 |
构建工具集成
如 Webpack 支持自动代码分割 + Prefetch,可为异步路由生成预取指令,实现智能预加载。
小娜提醒:
合理使用 Preload 和 Prefetch 能显著提升用户体验。
- 过度使用 Preload 可能造成资源竞争,影响主资源加载。
- 滥用 Prefetch 会浪费带宽。
建议结合实际用户行为和性能监控进行优化配置。
安全机制
- 同源策略(Same-Origin Policy):限制跨域资源访问,保障安全
- 协议、域名、端口相同才视为同源
- CORS(跨域资源共享):服务器通过响应头(
Access-Control-Allow-Origin
)允许跨域请求
缓存机制
- 强缓存:
Cache-Control
,Expires
- 协商缓存:
ETag
/If-None-Match
,Last-Modified
/If-Modified-Since
浏览器性能优化
解题思路
浏览器在页面加载和渲染过程中进行了大量优化,主要包括:
- DNS 预解析
- TCP 连接复用
- 资源预加载
- 关键渲染路径优化
- DOM 和 CSSOM 构建优化
- GPU 加速合成
- JavaScript 执行优化
- 缓存机制
- 懒加载与预渲染 等
这些优化措施贯穿“从用户输入 URL 到页面完全渲染显示”的整个流程。下面按浏览器工作阶段梳理主要优化策略:
1. DNS 预解析(DNS Prefetching)
- 作用:浏览器提前解析页面中可能出现的域名,减少后续请求的 DNS 查询延迟。
- 原理:DNS 查询是网络延迟的重要来源之一,预解析可将耗时操作提前执行。
- 实现:可通过
<link rel="dns-prefetch" href="//example.com">
或浏览器自动推测。
2. TCP 连接优化
- 连接池与复用:使用 TCP 连接池和 Keep-Alive,避免每个请求都三次握手。
- 多路复用:HTTP/2、HTTP/3 支持多路复用,多个请求共用一个连接,减少队头阻塞。
- 服务器推送:HTTP/2 支持 Server Push,提前发送客户端可能需要的资源。
3. 资源预加载与预取
- Preload:强制浏览器提前加载关键资源(如字体、JS/CSS),提高加载优先级。
- Prefetch:浏览器空闲时预加载未来可能用到的资源(如下一页 JS),提升导航速度。
- 调度:浏览器调度器根据资源类型和优先级安排加载顺序。
4. 关键渲染路径优化(Critical Rendering Path)
- 首屏优先:优先解析和渲染首屏内容,延迟非关键资源。
- 优化措施:
- 尽快构建 DOM 和 CSSOM(避免阻塞渲染)
- 关键 CSS 内联,减少外部阻塞
- 非关键 JS 异步加载(async/defer)
- 渲染树仅包含可见元素,避免不必要的计算
5. DOM 与 CSSOM 构建优化
- 增量解析:边接收 HTML 边构建 DOM,无需等待完整文档。
- 流式处理:CSS 解析支持流式,但 CSS 是渲染阻塞资源,浏览器会优先下载解析。
- 高效解析器:如 HTML5 解析算法,快速构建 DOM 树。
6. 布局、绘制与合成优化
- 分层机制:动画元素提升为合成层(如
transform
、will-change
),交由 GPU 处理,避免重排重绘。 - 合成阶段:仅合成图层,不涉及布局和绘制,极大提升性能。
- 硬件加速:GPU 处理变换、透明度等操作。
7. JavaScript 执行优化
- JIT 编译:如 V8 引擎将 JS 编译为机器码执行。
- 隐藏类与内联缓存:提升对象属性访问速度。
- 垃圾回收优化:分代回收、增量标记等减少卡顿。
8. 缓存机制
- 强缓存:
Cache-Control
、Expires
,资源直接本地读取。 - 协商缓存:
ETag
、Last-Modified
,服务器判断是否需要更新。 - 离线缓存:Service Worker + Cache API,支持 PWA 应用。
9. 懒加载(Lazy Loading)
- 图片/iframe 懒加载:仅当元素进入视口时才加载,减少初始负载。
- 原生支持:
loading="lazy"
属性。 - JS 实现:
Intersection Observer
监听元素可见性。
10. 预渲染(Prerendering)
- 作用:浏览器后台加载并渲染整个页面(如搜索结果中的高概率点击页),用户点击时瞬间显示。
- 注意:如
<link rel="prerender">
,但资源消耗大,需谨慎使用。
11. 内存与资源调度优化
- 多进程架构:Browser/Renderer/GPU Process 等,隔离页面,提升稳定性和安全性。
- 沙箱机制:渲染进程权限受限。
- 资源加载优先级:HTML > CSS > JS > 图片 > prefetch 等。
12. HTTP 缓存与 CDN 协同
- CDN 优先:浏览器与 CDN 配合,优先从边缘节点获取资源,降低延迟。
- 高效验证:使用 ETag 等机制。
扩展知识
- 关键渲染路径(Critical Rendering Path) 是前端性能优化的核心,涉及 DOM、CSSOM、Render Tree、Layout、Paint、Composite 六阶段。浏览器通过多种手段缩短路径。
- 性能分析工具:Chrome DevTools 的 Performance、Lighthouse 面板可分析优化效果。
- 新兴 API:如 Priority Hints(
<link rel="preload" importance="high">
)允许开发者显式指定资源加载优先级。