当前位置: 首页 > news >正文

Webrtc之SDP协议

SDP简介

SDP 最常用于 RTC 实时通话的协商过程,在 WebRTC 中,通信双方在连接阶段使用 SDP 来协商后续传输过程中使用的音视频编解码器(codec)、主机候选地址、网络传输协议等。

在实际的应用过程中,通信双方可以使用 HTTP、WebSocket、DataChannel 等传输协议来相互传送 SDP 内容,这个过程称作 offer/answer 交换,也就是发起方发送 offer,接收方收到 offer 后回复一个 answer。例如在下图的服务端架构中,客户端将 offer 发送给信令服务器,信令服务器转发给媒体服务器,媒体服务器将 offer 和自身的能力进行比较后得到 answer,信令服务器再将 answer转发给客户端,随后客户端和媒体服务器就可以进行 RTP 通信。

SDP 协议的设计可以参考 rfc4566 文档。它是一种具有特殊约定格式的纯文本描述文档,也就是它的内容都是由 UTF-8 编码的文本,有点类似于 JSON/XML。一个 SDP 会话描述包括若干行 type=value 形式的文本,其中 type 是一个区分大小写的字母,例如 v、m 等,value 是一个结构化的文本,格式不固定。通常 value 由若干分割符隔开的字段组成或者是一个字符串, 整个协议文本区分大小写。"=" 两侧不允许有空格存在。

SDP 由一个会话级描述(session level description)和多个媒体级描述(media level description)组成。会话级描述的作用域是整个会话,在 SDP 中,从 "v=" 行开始到第一个 "m=" 行之前都是属于会话级描述的内容。媒体级描述对某个媒体流的内容进行描述,例如某个音频流或者某个视频流,从某个 "m=" 行开始到下个 "m=" 行之前是属于一个媒体级描述的内容。如下图所示:

 SDP 中有的字段是必须的,有的字段是可选的,可选的字段在如下的示例中都使用 * 进行标记。 SDP 中 type 出现的顺序是固定的,按照如下顺序进行排列,这样可以增强解析器错误检测的能力,另外也可以简化解析器的实现。有一个很好的网站:webrtchacks.com/sdp-anatomy… 可用于学习 SDP,这个网站里面鼠标移动到 SDP 某一行时,就会显示这一行 SDP 的具体含义。

# 1. 会话级别的描述(及其字段)
v=  (protocol version)
o=  (originator and session identifier)
s=  (session name)
i=* (session information)
u=* (URI of description)
e=* (email address)
p=* (phone number)
c=* (connection information -- not required if included in all media)
b=* (zero or more bandwidth information lines)
# 2. 一个或多个时间描述(字段参见下文)
z=* (time zone adjustments)
k=* (encryption key)
a=* (zero or more session attribute lines)
# 3. 零个或多个媒体级别的描述(字段参见下文)# 时间描述的字段有这些
t=  (time the session is active)
r=* (zero or more repeat times)# 媒体级别的描述字段有这些
m=  (media name and transport address)
i=* (media title)
c=* (connection information -- optional if included at session level)
b=* (zero or more bandwidth information lines)
k=* (encryption key)
a=* (zero or more media attribute lines)

SDP示例

// SDP 版本信息v=0// session 信息// o=<username> <session-id> <session-version> <nettype> <addrtype> <unicast-address>o=- 1873022542326151139 2 IN IP4 127.0.0.1// s=<session name>s=-// t=<start-time> <stop-time>,如果不规定开始和结束时间,两个都填 0 即可t=0 0// 使用 "a=" 来扩展的 bundle 属性,其含义是 audio 和 video 使用同一个端口发送/接收,具体可以参考下方的 RFC 文档:// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54a=group:BUNDLE audio video// 列出当前SDP中所有的 media stream id,以空格分割// WMS 的含义是这里面的 media stream id 适配 webrtc 的 media stream// 参考 RFC 文档: https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-msid-01#section-3a=msid-semantic: WMS 34b34ced3c5623ea4213vx3// m=<media> <port> <proto> <fmt> ...// port=10 无实际含义,真正通信使用的端口由 ICE Candidate 指定// proto=UDP/TLS/RTP/SAVP 表示用 UDP 来传输 RTP 包,并使用 DTLS 加密// 后面的一串数字是 fmt,表示所有 codec 的 payloadtypem=audio 10 UDP/TLS/RTP/SAVPF 111 114 115 116 123 124 125// c=<nettype> <addrtype> <connection-address>c=IN IP4 0.0.0.0// a=rtcp:<port> [nettype addrtype connection-address]a=rtcp:10 IN IP4 0.0.0.0// ICE 信息,参考 RFC 文档: https://tools.ietf.org/html/rfc5245#section-15.4a=ice-ufrag:aZ/ba=ice-pwd:3tFwvgPAA2PK3pPWoJjVz4FJa=ice-options:trickle renomination// DTLS 信息,参考 RFC 文档: https://tools.ietf.org/html/rfc4572#section-5a=fingerprint:sha-256 5F:78:37:05:D7:83:46:05:F7:3F:17:35:2A:7E:81:D3:2D:26:71:87:8B:9F:57:02:53:30:E3:3E:B6:3E:49:D5// a=setup:<role>// role可选active/passive/actpass/holdconn,// 分别表示端点将发起一个传出连接、端点将接受传入连接、// 端点愿意接受传入连接或启动传出连接、端点暂时不想建立连接// 参考 rfc: https://tools.ietf.org/html/rfc4145#section-4a=setup:actpass// a=mid:<token>// 这个 token 在 a=group 那一行中也有出现,// 也就是说这里描述的媒体正是需要被 bundle 的// 参考 rfc: https://tools.ietf.org/html/rfc5888#section-6a=mid:audio// 以下是这个媒体支持的所有 RTP 扩展头,// 参考rfc: https://tools.ietf.org/html/rfc8285// a=extmap:<value>["/"<direction>] <URI> <extensionattributes>// value=ID// direction 可选 sendonly/recvonly/sendrecv/inactive,默认值 sendrecv// URI 就是这个扩展头的 URI,通信双方可以通过 URI 标明扩展头的含义让双方都能理解// 这里表示 ID=1 的扩展头是 audio level 扩展头,表示 RTP 包中会携带音频包音量大小// 参考 https://tools.ietf.org/html/rfc6464#section-4a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level// rtp stream 信息,参考 rfc: https://tools.ietf.org/html/draft-ietf-avtext-rid-09a=extmap:13 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id// 流的方向,sendrecv 表示可以收也可以发// 参考 rfc:https://tools.ietf.org/html/rfc3264a=sendrecv// 这一行表示 rtcp 和 rtp 复用一个端口,// 参考 rfc:https://tools.ietf.org/html/rfc5761 // 和 rfc:https://tools.ietf.org/html/rfc8035a=rtcp-mux// a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]// opus codec 的 payload,// 表明 fmt=111 就是用来传输 opus 数据的// 参考 rfc: https://datatracker.ietf.org/doc/html/rfc7587a=rtpmap:111 opus/48000/2// a=rtcp-fb:<payload type> [...]// 表示支持的 rtcp 反馈报文类型// 这个反馈报文是 tcc 带宽探测用的// 参考 https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01a=rtcp-fb:111 transport-cc// nack,表示 fmt=111 支持 nack 重传包a=rtcp-fb:111 nack// a=fmtp 用来描述 codec 的一些特性,例如这里表示期望的 opus 最小打包时间是 10ms,并且使用 inbandfeca=fmtp:111 minptime=10;useinbandfec=1// 指明了音频 RTX 包的 payloadtype// 参考 rfc:https://tools.ietf.org/html/rfc4588#section-8.6a=rtpmap:114 rtx/48000/2// apt 表示 fmt=114 的 RTX 包是用来重传 fmt=111 音频的a=fmtp:114 apt=111// 指明了 rsfec 包的 payloadtypea=rtpmap:123 rsfec/48000/2// 指明了 red 包的 payloadtype// 参考 https://tools.ietf.org/html/rfc2198a=rtpmap:124 red/48000/2// 指明了音频 RTX 包的 payloadtypea=rtpmap:125 rtx/48000/2// apt 表示 fmt=125 的 RTX 包是用来重传 fmt=124 的 red 包的a=fmtp:125 apt=124// ssrc-group 指明了一组 ssrc 之间的关系,FID 表明后一个 ssrc 是前一个 ssrc 的 rtx// https://tools.ietf.org/html/rfc5576#section-4.2a=ssrc-group:FID 2952055605 1713037948// cname 的内容是一个 16 位 Base64 字符串,含义是传输级的标识符,同一个 PeerConnection 的值相同// 参考 https://datatracker.ietf.org/doc/html/rfc8834#section-4.9a=ssrc:2952055605 cname:vqdagKn92E0lhuXn// 这里出现了两个字符串,// 前一个是 media stream id,后一个是 sender track id// media stream 主要用于音视频同步,每个 track 以 media stream id 作为 sync label 进行同步// 参考 https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-msida=ssrc:2952055605 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3a0// media stream ida=ssrc:2952055605 mslabel:34b34ced3c5623ea4213vx3// sender track ida=ssrc:2952055605 label:34b34ced3c5623ea4213vx3a0// video mediam=video 10 UDP/TLS/RTP/SAVPF 96 97 101 102 103c=IN IP4 0.0.0.0a=rtcp:10 IN IP4 0.0.0.0a=ice-ufrag:aZ/ba=ice-pwd:3tFwvgPAA2PK3pPWoJjVz4FJa=ice-options:trickle renominationa=fingerprint:sha-256 5F:78:37:05:D7:83:46:05:F7:3F:17:35:2A:7E:81:D3:2D:26:71:87:8B:9F:57:02:53:30:E3:3E:B6:3E:49:D5a=setup:actpassa=mid:video// 传输时间偏移扩展头// 参考 https://datatracker.ietf.org/doc/html/rfc5450a=extmap:2 urn:ietf:params:rtp-hdrext:toffset// abs-send-time 扩展头,gcc 带宽探测用的a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time// 视频朝向扩展头// 参考 https://datatracker.ietf.org/doc/html/rfc6184a=extmap:4 urn:3gpp:video-orientation// transport-cc 扩展头,tcc 带宽探测用的a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01// 扩展头的内容是对播放延迟限制的值a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay// 视频内容类型扩展头a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type// 这个扩展头用于传输每帧的时间信息a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing// 视频的色域空间扩展头a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/color-space// 传输视频 SDES 信息的扩展头// 参考:https://datatracker.ietf.org/doc/html/draft-ietf-avtext-rid-06a=extmap:13 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-ida=sendrecva=rtcp-mux// 支持 rtcp 压缩// 参考 https://datatracker.ietf.org/doc/html/rfc5506#section-1a=rtcp-rsize// 指明 fmt=96 就是用来传输 H264 编码的视频的a=rtpmap:96 H264/90000// remb 反馈报文,gcc 带宽探测用的a=rtcp-fb:96 goog-remba=rtcp-fb:96 transport-cc// FIR(完整帧内请求)反馈报文// 参考 https://datatracker.ietf.org/doc/html/rfc5104a=rtcp-fb:96 ccm fira=rtcp-fb:96 nack// PLI NACK 反馈报文// 参考 https://datatracker.ietf.org/doc/html/rfc5104a=rtcp-fb:96 nack pli// 后面的是一些 H264 的参数a=fmtp:96 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01fa=rtpmap:97 rtx/90000a=fmtp:97 apt=96;packetization-mode=1a=rtpmap:101 red/90000a=fmtp:101 packetization-mode=1a=rtpmap:102 rtx/90000a=fmtp:102 apt=101;packetization-mode=1a=rtpmap:103 rsfec/90000a=fmtp:103 packetization-mode=1// ssrc-group:SIM 表示后面的这些 ssrc 是同一个流的 simulcasta=ssrc-group:SIM 2955842370 1032318052a=ssrc-group:FID 2955842370 521905126a=ssrc-group:FID 1032318052 1492521545a=ssrc:2955842370 cname:vqdagKn92E0lhuXna=ssrc:2955842370 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3v0a=ssrc:2955842370 mslabel:34b34ced3c5623ea4213vx3a=ssrc:2955842370 label:34b34ced3c5623ea4213vx3v0a=ssrc:1032318052 cname:vqdagKn92E0lhuXna=ssrc:1032318052 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3a=ssrc:1032318052 mslabel:34b34ced3c5623ea4213vx3a=ssrc:1032318052 label:34b34ced3c5623ea4213vx3v0a=ssrc:521905126 cname:vqdagKn92E0lhuXna=ssrc:521905126 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3v0a=ssrc:521905126 mslabel:34b34ced3c5623ea4213vx3a=ssrc:521905126 label:34b34ced3c5623ea4213vx3v0a=ssrc:1492521545 cname:vqdagKn92E0lhuXna=ssrc:1492521545 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3v0a=ssrc:1492521545 mslabel:34b34ced3c5623ea4213vx3a=ssrc:1492521545 label:34b34ced3c5623ea4213vx3v0// 使用的 rsfec 的版本a=rsfec-version:1

参考文档

  • SDP 格式规定,RFC4566:datatracker.ietf.org/doc/html/rf…
  • offer/answer 交换过程,RFC3264:datatracker.ietf.org/doc/html/rf…
  • SDP 各字段解释示例:webrtchacks.com/sdp-anatomy…
  • segmentfault.com/a/119000003…

相关文章:

Webrtc之SDP协议

SDP简介 SDP 最常用于 RTC 实时通话的协商过程&#xff0c;在 WebRTC 中&#xff0c;通信双方在连接阶段使用 SDP 来协商后续传输过程中使用的音视频编解码器(codec)、主机候选地址、网络传输协议等。 在实际的应用过程中&#xff0c;通信双方可以使用 HTTP、WebSocket、Data…...

mfc140u.dll丢失错误解决方法的基本思路——四种修复mfc140u.dll的方法

当遇到mfc140u.dll丢失的错误时&#xff0c;意味着你的系统中缺失了一个重要的动态链接库文件&#xff0c;该文件是微软 Visual C Redistributable for Visual Studio 2015 的一部分&#xff0c;对于运行那些用 Visual C 开发的程序是必需的。今天就教你mfc140u.dll丢失错误解决…...

Python Django 后端架构开发: 中间件架构设计

&#x1f31f; Python Django 后端架构开发&#xff1a; 中间件架构设计 &#x1f539; 中间件项目测试&#xff1a;自定义中间件的 process_response 与 process_view 方法 在 Django 中&#xff0c;中间件是一种用于处理请求和响应的钩子&#xff0c;可以在视图处理前后对请…...

HTTP的认证方式

0.HTTP认证相关的一些基本概念 0.1 HTTP保护空间(HTTP Protection Space) 也称为认证领域(Authentication Realm),是指在HTTP认证中用来定义一组受保护资源的范围。保护空间通常由一个realm标识符来表示,它定义了用户需要提供凭据(如用户名和密码)才能访问的资源集合…...

10分钟学会LVM逻辑卷

华子目录 前言认识LVMLVM基本概念LVM整体流程LVM管理命令pvs&#xff0c;vgs&#xff0c;lvs命令pvs基本用法选项示例 vgs基本用法选项示例 lvs基本用法 pvcreate&#xff0c;vgcreate&#xff0c;lvcreate命令pvcreate示例 vgcreate基本用法示例选项 lvcreate基本用法示例 pvr…...

【gitlab】gitlab-ce:17.3.0-ce.0 之2:配置

参考阿里云的教程docker的重启 sudo systemctl daemon-reload sudo systemctl restart docker配置 –publish 8443:443 --publish 8084:80 --publish 22:22 sudo docker ps -a 當容器狀態為healthy時,說明GitLab容器已經正常啟動。 root@k8s-master-pfsrv:~...

第七十四:前端实现点击页面某个菜单跳转到对应的锚点功能

1.用js来实现 scrollIntoView方法 先定义个id或者class随意&#xff0c;因为我是循环好几个小模块所以用动态的来实现 点击的时候传对应的类名进行滑动 document.getElementById(item.variableCode).scrollIntoView({behavior:“smooth”}); 加上behavior:“smooth” 进行平…...

PyTorch分布式训练全攻略:DistributedDataParallel精解与实战

标题&#xff1a;PyTorch分布式训练全攻略&#xff1a;DistributedDataParallel精解与实战 在深度学习飞速发展的今天&#xff0c;模型的规模和数据集的体量不断增长&#xff0c;单机单卡的训练方式已难以满足需求。分布式训练以其卓越的扩展性和效率&#xff0c;成为解决这一…...

Python(TensorFlow)多模光纤光束算法和GPU并行模拟

&#x1f3af;要点 &#x1f3af;多模光纤包含光学系统线性和非线性部分 | &#x1f3af;单变量线性回归、多变量线性回归、人脸图像年龄预测、音频语音分类和 X 射线图像评估算法 | &#x1f3af;在空间光调制器记录海螺参数矩阵&#xff0c;光束算法多变量预测年龄 | &#…...

实战Kubernetes之快速部署 K8s 集群 v1.28.0

文章目录 一、前言二、主机准备三、系统配置3.1. 关闭防火墙及相关配置3.2. 修改主机名3.3. 主机名DNS解析3.4. 时间同步3.5. 配置网络3.6. 重启服务器 四、安装软件4.1. 安装 Docker4.2. 安装 cri-dockerd4.3. 添加国内YUM源4.4. 安装 kubeadm、kubelet 和 kubectl 五、Master…...

YOLO知识点总结:

分类&#xff1a; 即是将图像结构化为某一类别的信息&#xff0c;用事先确定好的类别(category)或实例ID来描述图片。这一任务是最简单、最基础的图像理解任务&#xff0c;也是深度学习模型最先取得突破和实现大规模应用的任务。其中&#xff0c;ImageNet是最权威的评测集&…...

合宙LuatOS AIR700 IPV6 TCP 客户端向NodeRed发送数据

为了验证 AIR700 IPV6 &#xff0c;特别新建向NodeRed Tcp发送的工程。 Air700发送TCP数据源码如下&#xff1a; --[[ IPv6客户端演示, 仅EC618系列支持, 例如Air780E/Air600E/Air780UG/Air700E ]]-- LuaTools需要PROJECT和VERSION这两个信息 PROJECT "IPV6_SendDate_N…...

git 如何生成sshkey公钥

打开git客户端 输入 ssh-keygen -t rsa -b 4096 -C "xxxxxxexample.com" 然后根据提示按enter 或者y 直到出现下图所示 打开 c盘的路径下的文件&#xff0c;/c/Users/18159/.ssh/id_rsa.pub 将id_rsa.pub中的公钥贴到git 网站上的SSH keys即可...

python从入门到精通:函数

目录 1、函数介绍 2、函数的定义 3、函数的传入参数 4、函数的返回值 5、函数说明文档 6、函数的嵌套调用 7、变量的作用域 1、函数介绍 函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能的代码段。 name "zhangsan"; length len(nam…...

【Android性能篇】如何分析 dumpsys meminfo 信息

一、dumpsys meminfo是什么 dumpsys meminfo 是一个用于分析Android设备内存使用情况的强大命令。 二、dumpsys meminfo的关键信息 要分析其输出信息&#xff0c;我们需要注意以下几个关键点&#xff1a; Total PSS by OOM adjustment&#xff1a;这个值表示每个进程的总比…...

c++进阶——继承的定义,复杂的菱形继承及菱形虚拟继承

目录 前言&#xff1a; 1.继承的概念及定义 1.1继承的概念 1.2 继承定义 1.2.2继承关系和访问限定符 1.2.3继承基类成员访问方式的变化 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 5.继承与友元 6. 继承与静态成员 7.复杂的菱形继承及菱…...

计算机网络:DNS、子网掩码、网关

参考&#xff1a; https://blog.csdn.net/weixin_55255438/article/details/123074896 https://zhuanlan.zhihu.com/p/65226634 在计算机网络中&#xff0c;DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;、子网掩码&#xff08;Subnet Mask&#xff09;…...

程序员如何学习开源项目

程序员如何学习开源项目 豆包MarsCode使用豆包MarsCode学习开源项目步骤导入git上开源的项目 豆包MarsCode https://www.marscode.cn/home 使用豆包MarsCode学习开源项目 步骤 https://www.marscode.cn/dashboard 导入git上开源的项目 找到项目的README.md文件&#xff0c;使…...

探索数据结构:红黑树的分析与实现

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 红黑树的介绍 1.1. 红黑树的引入 我们前面学习了AVL树&#xff0c;…...

【设计模式】装饰器模式和适配模式

装饰器模式 装饰器模式能够很好的对已有功能进行拓展&#xff0c;这样不会更改原有的代码&#xff0c;对其他的业务产生影响&#xff0c;这方便我们在较少的改动下对软件功能进行拓展。 类似于 router 的前置守卫和后置守卫。 Function.prototype.before function (beforeFn)…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...