原文链接:
https://mp.weixin.qq.com/s?__biz=MzIzMjY3MjYyOA==&mid=2247498075&idx=2&sn=6021a2f60b1e7c71ce4d7af6df0b9b89&chksm=e893e540dfe46c56323322e780d41aec1f851925cfce8b76b3f4d5cfddaa9c7cbb03a7ae4c25&scene=178&cur_album_id=3146991347015499781#rd

一、WebRTC ICE

1.1 ICE 是什么?

在 WebRTC(网页实时通信)技术体系中,ICE(Interactive Connectivity Establishment,交互式连接建立) 是解决 “设备间如何突破网络壁垒(如 NAT 网关)建立直接通信” 的核心协议。它通过整合 STUN(会话穿越实用工具)TURN(中继穿越实用工具),动态收集通信候选地址、检查连通性,并最终选择最优路径(优先 P2P,失败时降级为中继),确保实时音视频、数据传输的可靠性

1.2 为什么需要 ICE?

WebRTC 的目标是实现 “浏览器 / 终端设备间的直接通信(P2P)”,但现实网络中存在两大障碍:

  • IP 地址短缺:IPv4 地址耗尽导致绝大多数设备处于局域网内,仅拥有内网 IP(如 192.168.x.x、10.x.x.x),无法直接被公网设备访问。
  • NAT 网关隔离:NAT(网络地址转换)是解决 IP 短缺的核心技术,但它会 “隐藏” 内网设备的真实地址,仅允许内网设备主动发起的外网连接,拒绝外部设备的主动访问 —— 这直接阻断了 P2P 通信的可能性。

ICE 的核心思想正是绕开 NAT 限制:通过收集设备的 “通信候选地址(Candidate)”,尝试不同路径的连通性,最终找到一条能让两端互通的路径。

1.3 通信候选地址(Candidate)

ICE 为每个设备(称为 “代理”)收集多种 Candidate 地址(IP + 端口 + 传输协议的组合,WebRTC 中默认用 UDP),每种 Candidate 对应一种潜在的通信路径。核心类型如下:

Candidate 类型来源与作用适用场景
Host Candidate(本地候选)设备本地网卡的真实地址(如内网 IP 或公网 IP)两端处于同一局域网(如办公室内设备),或一端拥有公网 IP
Srflx Candidate(服务器反射候选)设备向 STUN 服务器发送请求,STUN 返回 NAT 网关的 “公网映射地址”(内网 IP 经 NAT 转换后的公网地址)两端均通过 圆锥型 NAT 接入公网,可通过反射地址实现 P2P 打洞
Prflx Candidate(对等反射候选)连通性检查过程中,通过对端的 STUN Binding 请求 “动态发现” 的 NAT 反射地址补充 Srflx 覆盖不到的场景(如对称型 NAT 下的临时映射地址)
Relay Candidate(中继候选)设备向 TURN 服务器请求,由 TURN 分配的 “中继地址”(所有数据通过 TURN 服务器转发)P2P 打洞失败时(如对称型 NAT 间通信),降级为中继传输
关键区分:Srflx 与 Prflx
  • Srflx 是通过 STUN 服务器主动获取的,提前通过信令交换给对端;
  • Prflx 是在 连通性检查阶段动态发现的,无需提前交换,仅在检查过程中生成。

1.4 STUN 与 TURN 协议

ICE 本身不直接 “穿越 NAT”,而是依赖 STUN 和 TURN 实现核心能力。二者分工明确:STUN 负责 “发现 NAT 映射地址” 和 “检查连通性”,TURN 负责 “P2P 失败时提供中继”

STUN:NAT 地址发现与连通性检查

STUN(Session Traversal Utilities for NAT)是一种轻量级协议,主要解决两个问题:

  1. 获取 NAT 公网映射地址:内网设备向 STUN 服务器发送 Binding Request,STUN 服务器返回设备的 “公网映射地址(MAPPED-ADDRESS)”,设备据此生成 Srflx Candidate。
  2. 验证连通性:ICE 用 STUN 的 Binding Request/Response 检查 “候选地址对(Candidate Pair)” 是否能互通(即 “打洞” 是否成功)。
(1)STUN 的版本演进:RFC3489 vs RFC5389

ICE 仅支持 RFC5389(现代 STUN),因为早期的 RFC3489(Classic STUN)存在诸多局限性:

特性RFC3489(Classic STUN)RFC5389(现代 STUN)
传输协议支持仅 UDP支持 UDP/TCP/TLS
安全认证支持短期 / 长期凭证认证
NAT 类型覆盖不支持对称型 NAT支持对称型 NAT 检测
IPv6 支持支持 IPv6
地址篡改防护提供 XOR-MAPPED-ADDRESS
(2)STUN 消息格式:20 字节头 + 可变属性

STUN 消息由 “固定头部” 和 “可变属性” 组成,结构如下:

在这里插入图片描述

  • 关键头部字段

    • 魔术字(Magic Cookie):固定值 0x2112A442,用于区分 STUN 消息与其他协议(如 RTP),并参与 XOR 地址计算。
    • 事务 ID(Transaction ID):96 位随机值,用于关联 “请求(Request)” 与 “响应(Response)”(避免多请求时混淆)。

ICE 核心扩展属性(STUN 为 ICE 新增的关键属性):

属性名作用
PRIORITY标识 Candidate 的优先级,用于计算 Candidate Pair 的优先级(决定检查顺序)
USE-CANDIDATE提名 Candidate Pair 为 “可用路径”,触发后续 DTLS 加密连接建立
ICE-CONTROLLING标识当前设备为 “控制角色(Controlling)”,携带 Tie-breaker 解决角色冲突
ICE-CONTROLLED标识当前设备为 “被控角色(Controlled)”,携带 Tie-breaker 解决角色冲突
XOR-MAPPED-ADDRESS对映射地址进行 XOR 加密,防止 NAT 网关篡改地址(修复 ALG 设备的兼容性)
MESSAGE-INTEGRITY基于 HMAC-SHA1 的消息完整性校验(用 ICE 协商的 ice-pwd 计算)
FINGERPRINTCRC32 指纹校验,进一步区分 STUN 消息与其他协议(如 RTP/RTCP)

TURN:P2P 失败时的中继方案

当 STUN 无法打通 NAT(如两端均为对称型 NAT)时,ICE 会降级为 TURN(Traversal Using Relays around NAT) 中继传输。TURN 本质是一个 “中继服务器”,核心作用是:

  1. 为设备分配 Relay Candidate(中继地址);
  2. 转发两端的音视频数据(所有流量经 TURN 服务器中转)。
TURN 的关键特性:
  • 协议兼容性:基于 STUN 扩展(除 ChannelData 消息外,其他消息格式与 STUN 一致),支持 UDP/TCP/TLS;
  • 权限控制:设备需先向 TURN 服务器发送 Allocate 请求 “申请中继资源”,并创建 Permission(许可)—— 仅允许被许可的对端地址通过 TURN 转发数据;
  • 效率优化:支持 ChannelData 消息(无 STUN 头部,减少开销),适合大流量传输。

1.5 ICE 细节

NAT 类型

NAT 网关的转发规则直接决定 P2P 能否成功,ICE 需先检测 NAT 类型,再选择合适的 Candidate。常见 NAT 类型分为 圆锥型 NAT对称型 NAT,其中圆锥型又细分为三类:

NAT 类型核心规则P2P 兼容性
完全圆锥型 NAT内网 IP:Port 映射为固定公网 IP:Port,任何外网设备可向该公网地址发送数据最佳(支持所有 P2P 场景)
IP 限制圆锥型 NAT内网 IP:Port 仅向 “主动访问过的外网 IP” 开放(端口不限)较好(仅限制 IP,支持大部分场景)
Port 限制圆锥型 NAT内网 IP:Port 仅向 “主动访问过的外网 IP:Port” 开放(IP + 端口双重限制)一般(需精准匹配端口)
对称型 NAT内网 IP:Port 向不同外网 IP:Port 发起请求时,映射不同的公网 IP:Port最差(P2P 几乎无法打通,需 TURN 中继)
NAT 类型检测流程:

ICE 代理通过向 STUN 服务器发送多轮请求,按以下顺序判断 NAT 类型:

  1. 检查防火墙是否阻断所有 UDP 包(若无法收到 STUN 响应,判定为 “UDP 阻断”);
  2. 检查设备是否拥有公网 IP(若本地 IP 与 STUN 返回的映射地址一致,判定为 “公网设备”);
  3. 检测是否为 “完全圆锥型 NAT”(向不同 STUN 服务器发送请求,若映射地址不变,且外部可主动访问);
  4. 检测是否为 “对称型 NAT”(向同一 STUN 服务器的不同端口发送请求,若映射地址变化,判定为对称型);
  5. 区分 “IP 限制” 与 “Port 限制圆锥型”(向同一 IP 的不同端口发送请求,若能收到响应则为 IP 限制,否则为 Port 限制)。

在这里插入图片描述

具体能否打通可以看下表:

在这里插入图片描述

ICE协议包括stun和turn协议,turn协议是stun协议的补充,可以简单粗暴理解为如果stun不通,那就走turn,turn可以理解为一个中继代理转发。

在这里插入图片描述

ICE 的角色与模式

ICE 定义了 “角色” 和 “模式”,用于规范两端的行为逻辑,避免冲突。

(1)ICE 角色:Controlling vs Controlled

ICE 两端分为两种角色,决定 “谁负责提名可用路径”:

  • Controlling(控制角色):主动提名 “可用的 Candidate Pair”,由 Offer 方(主动发起会话的设备)担任;
  • Controlled(被控角色):被动接受 Controlling 提名的路径,由 Answer 方(被动响应会话的设备)担任。
角色冲突解决:

若两端均误判为 Controlling(或 Controlled),通过 Tie-breaker(随机值) 解决:

  1. 冲突时,两端在 STUN Binding 请求中携带 ICE-CONTROLLING/ICE-CONTROLLED 属性及 Tie-breaker 值;
  2. 比较 Tie-breaker 大小:值更大的一端为 Controlling,另一端需切换为 Controlled;
  3. 若某端需切换角色,对端会返回 487(Role Conflict) 错误,触发角色变更。
ICE 模式:Full ICE vs Lite ICE

ICE 代理分为两种模式,对应不同的部署场景:

模式核心行为适用场景
Full ICE主动收集所有 Candidate,主动发起连通性检查,支持角色切换客户端设备(如浏览器、APP)
Lite ICE仅被动响应连通性检查(不主动发起),角色固定为 Controlled,SDP 含 a=ice-lite公网服务器(如媒体服务器、CDN 节点)

注意:Full ICE 与 Lite ICE 互通时,仅 Full ICE 端主动发起检查,Lite 端仅需回应即可。

ICE 的完整工作流程

ICE 从 “收集 Candidate” 到 “建立通信” 分为 8 个核心步骤,流程如下:

步骤 1:收集 Candidate(Candidate Collection)

ICE 代理从本地、STUN、TURN 收集所有可能的 Candidate,并去重(若两个 Candidate 的地址和 Base 地址相同,则删除重复项):

  • Host Candidate:遍历本地网卡(物理 / 虚拟),获取所有内网 / 公网 IP:Port;
  • Srflx Candidate:向 STUN 服务器发送 Binding Request,获取 NAT 公网映射地址;
  • Relay Candidate:向 TURN 服务器发送 Allocate 请求,获取中继地址;
  • Foundation 生成:为每个 Candidate 生成唯一标识(基于类型、IP、协议计算),用于后续去重。
步骤 2:交换 Candidate(Candidate Exchange)

两端通过 信令服务器 交换 Candidate(需与 SDP 协商同步),有两种交换方式:

  1. 传统方式:收集完所有 Candidate 后,将其嵌入 SDP 中一次性发送;
  2. Trickle ICE(涓流 ICE):SDP 与 Candidate 分开发送(SDP 先发送,Candidate 收集一个发一个),SDP 需包含 a=ice-options:trickle

优势:Trickle ICE 可缩短连接建立时间(无需等待所有 Candidate 收集完成),是 WebRTC 的默认方式。

SDP 中 Candidate 的格式示例:
a=candidate:240568271 1 udp 1686052607 174.139.8.82 64462 typ srflx raddr 10.1.1.19 rport 64462 generation 0 ufrag TWCy network-id 2

字段含义解析:

字段含义
240568271Foundation(Candidate 唯一标识)
1Component ID(媒体类型:1=RTP,2=RTCP;WebRTC 默认用 RTCP-mux 合并为 1)
udp传输协议(UDP/TCP)
1686052607Priority(Candidate 优先级,数值越大优先级越高)
174.139.8.82Candidate 地址(公网映射地址,对应 Srflx 类型)
64462端口号
typ srflxCandidate 类型(host/srflx/prflx/relay)
raddr 10.1.1.19Base 地址(Srflx 的本地内网地址)
ufrag TWCyICE 用户名片段(用于 STUN 认证,与对端 ufrag 组合为 USERNAME)
步骤 3:生成 Candidate Pair(候选地址对)

两端收到对方的 Candidate 后,按以下规则组合为 Candidate Pair(本端 Candidate + 远端 Candidate)

  • 匹配条件:Component ID 相同(如均为 RTP 的 1)且 传输协议相同(如均为 UDP);
  • 地址修整:若 Candidate 为 Srflx,需用其 Base 地址(本地内网地址)替换,确保检查逻辑正确。
步骤 4:连通性检查(Connectivity Checks)

ICE 按 Candidate Pair 的优先级 排序(优先级高的先检查),通过 STUN Binding Request/Response 验证 “该地址对是否能互通”。

(1)Candidate Pair 优先级计算

优先级决定检查顺序,公式如下(核心逻辑:优先选择 “本地优先” 且 “对端优先” 的组合):

Pair Priority = 2^32 * MIN(G, D) + 2 * MAX(G, D) + (G > D ? 1 : 0)
  • G:Controlling 角色的 Candidate 优先级;
  • D:Controlled 角色的 Candidate 优先级;
  • MIN(G,D)/MAX(G,D):取两者的最小值和最大值,确保 “高优先级 Candidate 优先匹配”。
(2)检查方式
  • Ordinary Checks(普通检查):Controlling 端按优先级顺序,主动向 Controlled 端发送 STUN Binding Request;
  • Triggered Checks(触发式检查):Controlled 端收到检查请求后,立即向 Controlling 端发起反向检查(提高效率,避免等待)。
(3)检查成功的条件
  1. 收到对端的 STUN Binding Success Response
  2. 地址对称:请求的 “源地址 = 响应的目的地址” 且 “请求的目的地址 = 响应的源地址”(排除 NAT 地址映射不对称的情况)。
(4)重传机制

若未收到响应,ICE 按 指数退避策略 重传(初始间隔 50ms,每次翻倍,直至最大重传次数或超时)。

步骤 5:生成 Valid List(有效地址列表)

将 “连通性检查成功” 的 Candidate Pair 按优先级排序,组成 Valid List(可用路径列表)。

步骤 6:提名 Candidate Pair(Nomination)

Controlling 角色 从 Valid List 中选择 “最优路径” 并提名,分为两种提名方式:

  • 普通提名(Regular Nomination):分两步检查
    1. 第一次检查:不带 USE-CANDIDATE 属性,仅验证连通性;
    2. 第二次检查:对 Valid List 中的 Pair 发送带 USE-CANDIDATE 的请求,确认提名。
  • 进取型提名(Aggressive Nomination):一步完成
    1. 所有检查请求均带 USE-CANDIDATE 属性;
    2. 第一个检查成功的 Pair 直接被提名(效率更高,WebRTC 默认采用)。
步骤 7:建立加密连接(DTLS)

提名完成后,两端基于 “选中的 Candidate Pair” 建立 DTLS(数据报传输层安全)连接——WebRTC 要求所有数据(音视频、DataChannel)必须加密,DTLS 负责证书交换、密钥协商,确保传输安全。

步骤 8:连接保活(Keep-Alive)

NAT 网关会 “超时清理” 长期无数据的连接(默认超时时间 30s~5min),ICE 通过以下方式保活:

  • 定期发送 STUN Binding Request/Indication(初始间隔 50ms,稳定后间隔 2.5s);
  • 若未收到响应,触发重传或重新选择 Valid List 中的备用路径。

ICE 的状态流转

ICE 代理在工作过程中会经历以下状态,用于标识连接进展:

状态含义
Waiting未开始连通性检查,等待 Candidate 收集或交换完成
In-Progress连通性检查已启动,但尚未有成功的 Pair
Succeeded已找到可用的 Candidate Pair,DTLS 连接建立完成,可开始数据传输
Failed所有 Candidate Pair 检查失败,且 TURN 中继不可用(连接彻底失败)
FrozenCandidate Pair 暂不检查(如等待其他 Pair 检查结果,后续可解冻)

在这里插入图片描述

二、WebRTC ICE的意义

2.1 价值

  • 解决 NAT 穿越难题:通过多 Candidate 类型和动态检查,覆盖 90% 以上的网络场景;
  • 优先 P2P 通信:减少对中继服务器的依赖,降低延迟(P2P 延迟通常 <100ms,中继延迟可能> 200ms);
  • 可靠性保障:Valid List 提供备用路径,某条路径中断时可快速切换到其他路径。

2.2 局限性

  • 依赖信令服务器:ICE 需信令服务器交换 SDP 和 Candidate,无法独立工作;
  • 对称型 NAT 需中继:对称型 NAT 下 P2P 无法打通,需依赖 TURN 服务器(增加带宽成本和延迟);
  • 防火墙限制:部分严格防火墙会阻断 UDP 端口,需降级为 TCP/TLS(效率较低)。

2.3 总结

ICE 是 WebRTC 实现 “实时 P2P 通信” 的核心支柱,它通过 “收集候选地址→检查连通性→提名最优路径” 的闭环流程,绕开了 NAT 网关的限制,同时整合 STUN 和 TURN 实现 “P2P 优先、中继兜底” 的通信策略。理解 ICE 的工作原理,是排查 WebRTC 连接失败(如 “无法建立 P2P 连接”“延迟过高”)的关键 —— 例如,连接失败可能是 STUN/TURN 服务器不可用、NAT 类型为对称型且无中继资源,或 Candidate 交换不完整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97843.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97843.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97843.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux0.12 head.s代码解析

重新设置IDT和GDT&#xff0c;为256个中断门设置默认的中断处理函数检查A20地址线是否启用设置数学协处理器将main函数相关的参数压栈设置分页机制&#xff0c;将页表映射到0~16MB的物理内存上返回main函数执行 源码详细注释如下: /** linux/boot/head.s** (C) 1991 Linus T…

Maven动态控制版本号秘籍:高效发包部署,版本管理不再头疼!

作者&#xff1a;唐叔在学习 专栏&#xff1a;唐叔的Java实践 关键词&#xff1a;Maven版本控制、versions插件、动态版本号、持续集成、自动化部署、Java项目管理 摘要&#xff1a;本文介绍如何使用Maven Versions插件动态控制项目版本号和依赖组件版本号&#xff0c;实现无需…

简述:普瑞时空数据建库软件(国土变更建库)之一(变更预检查部分规则)

简述&#xff1a;普瑞时空数据建库软件&#xff08;国土变更建库&#xff09;之一(变更预检查部分规则) 主要包括三种类型&#xff1a;常规检查、行政区范围检查、20X异常灭失检查 本blog地址&#xff1a;https://blog.csdn.net/hsg77

shell中命令小工具:cut、sort、uniq,tr的使用方式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、cut —— 按列或字符截取1. 常用选项2. 示例二、sort —— 排序&#xff08;默认按行首字符升序&#xff09;1. 常用选项常用 sort 命令选项三、uniq —— 去…

【Linux】Linux开发必备:Git版本控制与GDB调试全指南

前言&#xff1a;在Linux开发流程中&#xff0c;版本控制与程序调试是保障项目稳定性和开发效率的两大核心环节。Git作为当前最主流的分布式版本控制系统&#xff0c;能高效管理代码迭代、追踪修改记录并支持多人协同开发&#xff1b;GDB&#xff08;GNU调试器&#xff09;是Li…

实现 TypeScript 内置工具类型(源码解析与实现)

目标读者&#xff1a;已经熟悉 TypeScript 基础语法、泛型、条件类型的同学。本文按常见工具类型的分类与顺序实现并解释 Partial、Required、Readonly、Pick、Omit、Record、Exclude、Extract、NonNullable、ReturnType、Parameters、ConstructorParameters、InstanceType、Th…

Spring Boot + Nacos 配置中心示例工程

1️⃣ 工程结构 nacos-demo├── pom.xml└── src├── main│ ├── java│ │ └── com.example.nacosdemo│ │ ├── NacosDemoApplication.java│ │ ├── config│ │ │ └── AppProperties.java│ │ └── cont…

(二)文件管理-基础命令-pwd命令的使用

文章目录1. 命令格式2. 基本用法3. 高级用法4. 注意事项1. 命令格式 pwd [OPTION]...[OPTION]: 可选选项&#xff0c;用于改变命令的默认行为。最主要的两个选项是 -L 和 -P。它不需要任何参数&#xff08;如文件名或目录名&#xff09; 2. 基本用法 用法&#xff1a;pwd 是…

Leetcode_202.快乐数_三种方法解决(普通方法解决,哈希表解决,循环链表的性质解决_快慢指针)

目录第一种方法&#xff1a;暴力解法暴力ac代码&#xff1a;第二种方法&#xff1a;哈希表哈希表ac代码:第三种方法&#xff1a;根据循环链表的性质(快慢指针)第一种方法&#xff1a;暴力解法 最暴力的思路就是直接使用循环往下一直计算&#xff0c;这样特别浪费时间&#xff…

代码随想录刷题Day48

这次博客主要是对做过的关于二叉树系列的题目进行整理和分类。二叉树&#xff0c;要处理整个树&#xff0c;一般少不了遍历。遍历主要可以分为&#xff1a;递归系列、层序遍历。如果不遍历的话&#xff0c;那就是处理特殊的树了&#xff0c;比如完全二叉树。递归系列基本的递归…

汽车工装结构件3D扫描尺寸测量公差比对-中科米堆CASAIM

汽车制造过程中&#xff0c;工装结构件的尺寸精度对整车装配质量和生产进度有重要影响。传统测量工具如卡尺和三坐标测量机采用接触式工作方式&#xff0c;检测过程耗时较长&#xff0c;对于具有复杂曲面特征的工件&#xff0c;难以全面获取尺寸数据。激光三维扫描技术改变了传…

Docker Pull 代理配置方法

本文介绍通过网络代理加速Docker镜像拉取的方法。 配置方法 当执行docker pull从Docker Hub 拉取镜像时&#xff0c;其网络连接由守护进程docker daemon进行维护。 要修改其代理设置&#xff0c;可配置其systemd服务&#xff0c;步骤如下&#xff1a; &#xff08;1&#xf…

机电装置:从基础原理到前沿应用的全方位解析

本文由「大千AI助手」原创发布&#xff0c;专注用真话讲AI&#xff0c;回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我&#xff0c;一起撕掉过度包装&#xff0c;学习真实的AI技术&#xff01; 1 机电装置的基本概念与发展历程 机电装置&#xff08;Mechatronic D…

《SVA断言系统学习之路》【03】关于布尔表达式

序列中使用的表达式基于其所含变量的采样值进行评估。表达式评估的结果为布尔值&#xff0c;其解释方式与过程性if语句条件中的表达式完全相同&#xff1a;若表达式计算结果为X、Z 或 0&#xff0c;则被解释为假&#xff1b;否则即为真。但是&#xff0c;对可出现在并发断言中的…

指针高级(2)

6.数组指针#include <stdio.h> int main() {/*练习&#xff1a;利用指针遍历数组*///1.定义数组int arr[] { 10,20,30,40,50 };int len sizeof(arr) / sizeof(int);//2.获取数组的指针//实际上获取的&#xff1a;数组的首地址int* p1 arr;int* p2 &arr[0];printf…

如何高效记单词之:抓住首字母——以find、fund、fond、font为例

find、fund、fond、font这几个单词&#xff0c;你都认识吗&#xff1f;这几个单词&#xff0c;意思大体如下&#xff1a; find v.找到&#xff1b;发现fund n.基金fond a.喜欢的&#xff1b;喜爱的&#xff1b;深情的font n.字体&#xff0c;字型&#xff0c;字形 这几个单词在…

Ubuntu下把 SD 卡格式化为 FAT32

在 Ubuntu 下把 SD 卡格式化为 FAT32&#xff0c;按下面做&#xff08;会抹掉整卡数据⚠️&#xff09;&#xff1a; 1) 找到你的 SD 卡设备名 lsblk -p记下整盘设备&#xff0c;比如 /dev/sdb&#xff08;USB 读卡器常见&#xff09;或 /dev/mmcblk0&#xff08;内置读卡器&am…

涉私数据安全与可控匿名化利用机制研究(上)

文章目录前言一、涉私数据的概述及分类&#xff08;一&#xff09;涉私数据的“知情同意原则”&#xff08;二&#xff09;涉私数据的分类二、涉私数据可控匿名化利用机制&#xff08;一&#xff09;数据产品与涉私数据的利用形式&#xff08;二&#xff09;通过可信数据空间受…

Redis 的跳跃表:像商场多层导航系统一样的有序结构

目录 一 、从 "超市货架" 的痛点看跳跃表的价值 1.1、跳跃表与商场导航系统的结构对应 1. 1.1、zskiplistNode&#xff1a;带导航标记的 "商品"&#xff08;跳跃表节点&#xff09; 1.1.1.1、level []&#xff1a;商品上的多层导航标记 1.1.1.2、back…

小程序点击之数据绑定

<return /><view class"all-wrap" style"padding-top:{{topHeight}}px;"><view class"my-title">我的收藏</view><scroll-viewclass"collect-list-container"scroll-yscroll-top"{{scrollTop}}"…