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

WebRTC 通话原理:从协商到通信

在实时音视频通信领域,WebRTC(Web Real-Time Communication)凭借其开源、无需插件且能在浏览器中直接实现高质量通信的特性,成为开发者的热门选择。本文将深入解析 WebRTC 通话原理,涵盖媒体协商、网络协商、网络穿越(STUN)、中继转发(TURN)以及一对一通话信令服务器时序等核心内容,助你揭开 WebRTC 通信的神秘面纱。​

一、媒体协商:确定通信 “语言”​

媒体协商是 WebRTC 通话的基石,其核心在于通信双方就媒体格式、编解码器、分辨率、帧率等关键参数达成共识,确保双方能够顺畅 “对话”。在 WebRTC 体系中,这一过程主要依托 SDP(Session Description Protocol,会话描述协议)来实现。​

1. SDP 协议

本小节参考:

SDP协议是什么,详解SDP协议-CSDN博客

【音视频开发】 : SDP协议-CSDN博客

SDP 采用纯文本格式,以结构化的方式描述多媒体会话属性,其内容由多个字段组成,每个字段都承载着特定的信息,其基本格式如下:

<type>=<value>

以下是几个关键字段及其作用:​

  • v=:版本号字段,标识 SDP 协议的版本,目前常用版本为 0 。​
v=0
  • o=:拥有者 / 创建者字段,包含用户名、会话 ID、会话版本等信息,用于唯一标识一个会话。​
	o=<username> <sessionid> <version> <network type> <address type> <address>
  • s=:会话名称字段,描述会话的主题或用途,例如 “WebRTC 音视频通话”。​
s=<sessionname>
  • c=:表示媒体的连接信息,会话级描述中或中媒体级描述必至少有一个”c=“。
c=<networktype> <address type> <connection address>
  • t=:会话时间字段,指明会话的开始时间和结束时间,在持久连接的 WebRTC 通话中,该字段通常设置为 0 0,表示会话无固定时间限制(单位秒)。​
t=<start time>  <stop time>
  • m=:媒体描述字段,是媒体协商的核心部分。它会明确媒体类型(如 audio 表示音频,video 表示视频)、传输端口、传输协议(通常为 RTP/AVP,其中 AVP 代表 Audio/Video Profile),以及该媒体流支持的有效载荷类型(即编解码器)。例如 m=video 9 UDP/TLS/RTP/SAVPF 100 101 ,表示这是一个视频媒体流,使用 UDP 协议,基于 TLS 进行安全传输,采用 RTP 协议,支持 SAVPF(可扩展的音视频分布简档),有效载荷类型 100 和 101 对应不同的视频编解码器。​
m=<media><port> <transport> <fmt list>
  • a=:属性字段,用于补充媒体描述的详细信息,如编码参数、带宽限制、媒体控制等。例如 a=rtpmap:100 VP8/90000 ,表示有效载荷类型 100 对应的是 VP8 视频编解码器,采样率为 90000Hz 。​
a=rtpmap:<payload type><encoding name>/<clock rate>[/<encodingparameters>]

通过这些字段的组合,SDP 能够全面、准确地描述多媒体会话的各项属性,为媒体协商提供清晰的信息基础。​

示例:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=VLC media player
c=IN IP4 127.0.0.1
t=0 0
a=tool:vlc 2.2.4
m=video 5004 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=64001F;sprop-parameter-sets=Z0IAH5WoFAFuQA==,aM48gA==
a=control:streamid=0

2. Offer 与 Answer 的生成与交互细节​

当 A 端发起通话请求时,会调用 WebRTC API 中的 createOffer 方法生成 SDP Offer。在生成过程中,浏览器或应用会根据设备硬件能力和软件配置,罗列出自身支持的媒体参数组合。例如,在视频方面,可能支持 VP8、VP9、H.264 等多种编码格式,每种格式又对应不同的分辨率和帧率选项;音频方面,可能支持 Opus、PCM 等编码格式,以及不同的采样率和声道数。这些信息都会被整合到 SDP Offer 中。​

A 端生成 Offer 后,通过信令服务器将其发送给 B 端。B 端接收到 Offer 后,会对其中的媒体参数进行逐一分析。首先,B 端会检查自身设备和软件是否支持 Offer 中的媒体类型和编解码器。如果支持,B 端会根据自身的性能和资源情况,从支持的参数中选择最优的组合,然后调用 createAnswer 方法生成 SDP Answer。例如,如果 B 端设备性能有限,对于视频编码可能会选择相对低复杂度的 VP8,而不是 H.264 。​

B 端生成 Answer 后,同样借助信令服务器将其返回给 A 端。A 端接收到 Answer 后,会对比 Answer 中的参数与自己 Offer 中的参数,确认双方是否就媒体参数达成一致。若存在不一致或无法支持的参数,可能需要重新发起协商,或者采取默认的兼容设置,以保证通话能够顺利进行。​

3. 媒体协商过程中的异常处理与兼容性​

在实际网络环境中,媒体协商并非总是一帆风顺,可能会遇到各种异常情况。比如,由于网络延迟或丢包,B 端可能无法完整接收 A 端发送的 Offer,导致解析失败。此时,B 端可以通过信令服务器向 A 端发送错误反馈,请求重新发送 Offer。​

另外,不同浏览器或设备对 WebRTC 的支持程度存在差异,这也会影响媒体协商的结果。例如,某些老旧浏览器可能不支持最新的编解码器,或者对 SDP 协议的某些扩展字段解析存在问题。为了提高兼容性,开发者可以在协商过程中设置一些默认的、广泛支持的媒体参数作为保底选项。同时,还可以采用渐进式协商策略,先尝试使用高级的媒体参数进行协商,如果失败,则逐步降低参数要求,直至找到双方都支持的配置。

二、网络协商:规划数据传输路径​

网络协商在 WebRTC 通话中至关重要,它的核心使命是为通信双方敲定数据传输的路径与方式,涉及网络地址、端口以及传输协议等关键要素的确定。WebRTC 采用 ICE(Interactive Connectivity Establishment,交互式连接建立)框架,通过系统化的流程与策略,实现高效、稳定的数据传输链路搭建(ICE 主要用于实现端到端的通信连接,尤其是在 P2P(Peer-to-Peer)协议中,通常与 STUN(Session Traversal Utilities for NAT)和 TURN(Traversal Using Relays around NAT)一起使用)。

1. ICE 框架的核心构成与工作机制​

ICE 框架主要由三个关键部分组成:候选地址收集、候选地址交换、候选地址检查和连接建立。​

候选地址收集:​

ICE 会从多个渠道收集候选地址,为后续的连接尝试提供多种可能性。这些候选地址主要包括以下类型:​

  • 主机候选地址(Host Candidate):即设备在本地网络中的真实 IP 地址和端口。例如,当设备连接到家庭局域网时,获取到的 192.168.1.x 这类内网 IP 地址及其对应的端口,就构成了主机候选地址。这是最直接的连接方式,若双方处于同一局域网内,使用主机候选地址进行连接能实现最低延迟的数据传输。​
  • 服务器反射候选地址(Server-Reflexive Candidate,简称 SRF 候选地址):当设备处于 NAT(Network Address Translation,网络地址转换)设备之后时,设备自身无法直接获取其在公网中的地址。此时,设备会向 STUN(Session Traversal Utilities for NAT,NAT 会话遍历实用工具)服务器发送请求。STUN 服务器接收到请求后,根据 NAT 设备映射的公网地址和端口信息,将其返回给设备,这个返回的公网地址和端口就成为了服务器反射候选地址。例如,设备在内网的 IP 地址是 192.168.1.100:5000,经过 NAT 转换后,在公网的地址变为 123.123.123.123:6000,STUN 服务器将 123.123.123.123:6000 返回给设备,作为服务器反射候选地址 。​
  • 中继候选地址(Relay Candidate):在复杂网络环境下,当通过主机候选地址和服务器反射候选地址都无法建立连接时,就需要借助 TURN(Traversal Using Relays around NAT,使用中继穿越 NAT)服务器。TURN 服务器会为设备分配一个公网地址和端口,这个地址和端口就是中继候选地址。设备将数据发送给 TURN 服务器,再由 TURN 服务器转发给通信对方,实现数据的中继传输。​

候选地址交换:

通过信令协议(如 SIP、WebRTC 等),每个端点将其候选地址发送给对方,确保双方都能得到彼此的候选地址。

候选地址收集与交换示意图如下:

候选地址检查:​

收集到候选地址后,ICE 会对这些地址进行检查,判断其可用性。ICE 采用 “候选地址对” 的方式进行检查,即从两端设备的候选地址中各选取一个地址组成一对,然后使用 STUN 协议进行连通性测试。例如,A 端的一个候选地址与 B 端的一个候选地址组成一对,ICE 会尝试在这两个地址之间发送探测数据包(相对端上方发STUN Binding请求),根据是否能收到响应(STUN四次握手)来判断该地址对是否可用。在测试过程中,ICE 会遵循一定的优先级顺序(ICE规定了优先级计算方法,两端计算得到的优先级相同),优先测试主机候选地址,因为其理论上能提供最佳的传输性能;若主机候选地址测试失败,再依次测试服务器反射候选地址和中继候选地址。​

连接建立:​

经过候选地址检查,ICE 会从所有可用的候选地址对中,筛选出最优的一对来建立连接。最优地址对的选择通常基于连接的稳定性、延迟等因素。一旦确定了最优地址对,通信双方就会基于该地址对进行数据传输,正式建立起 WebRTC 通话的数据链路。​

2. 网络协商与其他组件的协同工作​

网络协商并非孤立进行,而是与 WebRTC 的其他组件紧密协作。在媒体协商阶段确定了媒体格式和编解码器后,网络协商要确保这些媒体数据能够顺利传输。例如,对于高码率的视频数据传输,网络协商需要选择带宽足够且稳定的传输路径;对于实时性要求极高的音频数据,网络协商要尽量降低传输延迟。​

同时,网络协商与 STUN、TURN 服务器密切配合。当需要获取服务器反射候选地址时,ICE 会与 STUN 服务器交互;在使用中继候选地址进行数据传输时,则依赖 TURN 服务器的中继转发功能。此外,网络协商的结果也会反馈给信令服务器,信令服务器会将相关的网络连接信息传递给通信双方,确保双方都知晓数据传输的路径和方式,从而实现无缝的实时通信。​

网络协商通过 ICE 框架的高效运作,结合 WebRTC 其他组件的协同配合,能够在复杂多变的网络环境中,为 WebRTC 通话规划出一条稳定、高效的数据传输路径,保障音视频数据的流畅传输。​

三、网络穿越(STUN):突破网络限制​

在实际网络环境中,通信双方往往处于不同的网络环境,如 NAT(Network Address Translation,网络地址转换)后面。NAT 会隐藏内部网络设备的真实 IP 地址,导致外部设备无法直接与内部设备建立连接,这就需要网络穿越技术来解决。​

STUN(Session Traversal Utilities for NAT,NAT 会话遍历实用工具)是 WebRTC 中常用的网络穿越技术。STUN 服务器的作用是帮助客户端获取其在公网中的 IP 地址和端口。客户端向 STUN 服务器发送请求,STUN 服务器接收到请求后,根据 NAT 设备映射的公网地址和端口信息,将其返回给客户端。客户端获取到公网地址后,就可以将该地址作为候选地址,与其他客户端进行连接尝试。这样,即使客户端位于 NAT 设备之后,也能实现与外部设备的通信。​

四、中继转发(TURN):保障通信畅通​

当 STUN 无法实现直接连接时,就需要借助 TURN(Traversal Using Relays around NAT,使用中继穿越 NAT)服务器来进行中继转发。TURN 服务器充当数据中转站的角色,接收来自一端的数据,然后转发给另一端。​

TURN 服务器不仅可以处理音视频数据,还能处理其他类型的媒体数据。虽然使用 TURN 服务器会增加一定的传输延迟和服务器负载,但在复杂的网络环境下,它是确保通信能够顺利进行的重要手段。例如,当双方都处于对称 NAT 后面,无法通过 STUN 直接建立连接时,TURN 服务器就成为了实现通信的关键。​

有关STUN,TURN等详细细节请参考我的文章:WebRTC:去中心化网络P2P框架解析-CSDN博客

五、一对一通话信令服务器时序​

信令服务器在 WebRTC 一对一通话中起着桥梁作用,负责传递双方的媒体协商信息、网络协商信息等。以下是一对一通话信令服务器时序的详细流程,通过时序图来直观呈现:

1. 连接初始化阶段​

呼叫方 A 和接收方 B 首先分别与信令服务器建立连接。A 向信令服务器发送连接请求,携带自身用户 ID(如 userA),信令服务器接收请求后进行处理,为 A 分配唯一的会话 ID(如 session_123),并返回连接成功的响应。

紧接着,B 也向信令服务器发送连接请求,附带其用户 ID(如 userB),信令服务器同样为 B 分配会话 ID(如 session_456),并告知 B 连接成功。此时,信令服务器记录下 A 和 B 这两个在线用户的相关信息,为后续的通话交互做好准备。

2. 呼叫发起与接受阶段

A 决定发起呼叫,向信令服务器发送呼叫请求,明确指定呼叫的目标用户为 B。信令服务器接收到该请求后,迅速将其转发给 B,同时附上 A 的相关元数据(如用户标识、设备信息等)。

B 收到呼叫请求后,在其设备上展示来电提示(如响铃、显示来电界面等)。当 B 决定接受呼叫时,向信令服务器发送接受呼叫的响应。信令服务器收到 B 的响应后,及时转发给 A,通知 A 呼叫已被接受,双方即将进入通话流程。

3.媒体协商信令交互​

A 在得知呼叫被接受后,调用相关 API 创建 SDP Offer,其中包含了自身提议的媒体参数,例如视频分辨率为 1080p,音频编码格式为 Opus,视频编码格式为 H.264 等。A 将生成的 SDP Offer 发送给信令服务器,信令服务器再将其转发给 B。

B 接收到 SDP Offer 后,对其中的参数进行解析,并结合自身设备和网络情况,选择合适的媒体参数,比如将视频分辨率调整为 720p,音频和视频编码格式保持为 Opus 和 H.264,然后创建 SDP Answer。B 将 SDP Answer 发送给信令服务器,信令服务器再转发给 A。至此,双方通过信令服务器完成了媒体协商,确定了最终使用 720p 分辨率,以及 H.264/Opus 编码格式进行音视频传输。

4. 网络协商信令交互​

为了建立有效的网络连接,A 和 B 需要进行网络协商,交换 ICE 候选地址。A 先向 STUN 服务器发送请求,获取公网地址,即服务器反射候选地址(SRF 候选),STUN 服务器返回对应的公网 IP(如 1.2.3.4:5000 )。在一些复杂的网络环境下,A 还会向 TURN 服务器请求中继地址(可选操作),TURN 服务器返回中继候选地址(如中继 IP: 5.6.7.8:6000 )。A 将收集到的所有 ICE 候选地址整理成列表,发送给信令服务器。

同样地,B 也向 STUN 服务器请求公网地址,获取自身的 SRF 候选(如公网 IP: 9.8.7.6:5500 ),并在必要时向 TURN 服务器请求中继地址(如中继 IP: 4.3.2.1:6500 ),然后将自己的 ICE 候选地址列表发送给信令服务器。信令服务器分别将 A 和 B 的候选地址列表转发给对方,使得双方都获取到了彼此的网络连接候选地址信息。

5. ICE 连接建立阶段

在拥有了双方的 ICE 候选地址后,开始进行 ICE 连接建立过程。A 和 B 会依次遍历候选地址对进行测试。首先尝试使用主机候选地址(A - Host vs B - Host)进行连接测试,如果双方处于同一局域网内,直接连通成功,B 向 A 返回 ICE 响应,标记连接成功。

若在同一局域网测试失败,说明双方处于跨 NAT 网络环境,此时尝试使用 STUN 穿透,即使用服务器反射候选地址(A - SRF vs B - SRF)进行连接测试。如果 STUN 穿透成功,B 同样向 A 返回 ICE 响应,确认连接成功。

若 STUN 穿透也失败,表明网络环境较为复杂,属于对称 NAT 情况,此时 A 将数据发送给 TURN 服务器的中继地址,TURN 服务器再将数据转发给 B,通过中继方式建立连接。

6. 通话控制信令交互​

当 ICE 连接成功建立后,通话进入媒体流传输阶段。A 开始向 B 发送视频流(采用 720p 分辨率、H.264 编码)和音频流(Opus 编码),同时 B 也向 A 发送相应的视频流和音频流,实现了音视频的双向实时传输,双方能够正常进行通话交流。

7. 通话结束阶段

当 A 想要结束通话时,向信令服务器发送挂断请求。信令服务器将该请求转发给 B,B 接收到请求后,停止媒体流的传输,并向信令服务器发送挂断确认。信令服务器再将 B 的挂断确认转发给 A,A 也停止媒体流传输。至此,双方的通话结束,整个一对一通话的信令交互流程完成。

相关文章:

WebRTC 通话原理:从协商到通信

在实时音视频通信领域&#xff0c;WebRTC&#xff08;Web Real-Time Communication&#xff09;凭借其开源、无需插件且能在浏览器中直接实现高质量通信的特性&#xff0c;成为开发者的热门选择。本文将深入解析 WebRTC 通话原理&#xff0c;涵盖媒体协商、网络协商、网络穿越&…...

InforSuite AS 可以发布django和vue项目是否可行

InforSuite AS 是浪潮推出的企业级中间件平台&#xff0c;主要用于应用集成、流程管理、数据交换等场景&#xff0c;其核心功能更偏向于 Java EE 应用的部署和管理&#xff08;如支持 WAR/EAR 包&#xff09;。关于能否直接发布 Django&#xff08;Python 框架&#xff09;和 V…...

【中级软件设计师】网络攻击(附软考真题)

【中级软件设计师】网络攻击&#xff08;附软考真题&#xff09; 目录 【中级软件设计师】网络攻击&#xff08;附软考真题&#xff09;一、历年真题二、考点&#xff1a;网络攻击1、拒绝服务攻击&#xff08;DoS攻击&#xff09;2、重放攻击3、特洛伊木马4、网络监听5、SQL注入…...

CSS图片垂直居中问题解决方案

在 CSS 中&#xff0c;使用 vertical-align: middle 导致图片略微向下偏移的现象&#xff0c;本质上是由于 行内元素的基线对齐规则 和 父容器上下文环境 共同作用的结果。以下是具体原因和解决方案&#xff1a; 原因详解 1. vertical-align: middle 的真实含义 该属性 不会让…...

P1601 A+B Problem(高精)

题目描述 高精度加法&#xff0c;相当于 ab problem&#xff0c;不用考虑负数。 输入格式 分两行输入。a,b≤10500。 输出格式 输出只有一行&#xff0c;代表 ab 的值。 输入输出样例 输入 1 1 输出 2 输入 1001 9099 输出 10100 说明/提示 20% 的测试数据…...

鸿蒙OSUniApp实现个性化的搜索框与搜索历史记录#三方框架 #Uniapp

使用UniApp实现个性化的搜索框与搜索历史记录 在移动端应用开发中&#xff0c;搜索功能几乎是标配&#xff0c;而一个好的搜索体验不仅仅是功能的实现&#xff0c;更是用户留存的关键。本文将分享如何在UniApp框架下打造一个既美观又实用的搜索框&#xff0c;并实现搜索历史记录…...

鸿蒙OSUniApp 制作自定义弹窗与模态框组件#三方框架 #Uniapp

UniApp 制作自定义弹窗与模态框组件 前言 在移动应用开发中&#xff0c;弹窗和模态框是用户交互的重要组成部分&#xff0c;它们用于显示提示信息、收集用户输入或确认用户操作。尽管 UniApp 提供了基础的交互组件如 uni.showModal() 和 uni.showToast()&#xff0c;但这些原…...

web第一次课后作业--运行一个java web项目

一、创建java web项目 1.新建java EE --> 模版&#xff1a;Web应用程序 2.选择版本&#xff1a;Java EE 8 3. 配置tomcat 二、页面效果 默认页面 跳转页面 三、代码 3.1 默认页面 <% page contentType"text/html; charsetUTF-8" pageEncoding"UTF-8…...

工业互联网

工业互联网全景解析 工业互联网是工业数字化、网络化、智能化转型升级的重要抓手&#xff0c;是实现中国制造 2025 战略目标的重要路径&#xff0c;对于推动我国实体经济高质量、可持续发展&#xff0c;建设制造强国、网络强国&#xff0c;意义重大。2017 年&#xff0c;我国提…...

论QT6多线程技术

前言 以前我多线程使用传统的继承qthread重写run()或者继承qrunable类把对象丢到线程池解决。经过昨天的面试让我了解到新的技术&#xff0c;我之前看到过只不过没有详细的去了解movetotread技术&#xff0c;这个技术是qt5推出的&#xff0c;qt6还在延续使用 代码结构 以下是…...

TensorFlow深度学习实战(16)——注意力机制详解

TensorFlow深度学习实战&#xff08;16&#xff09;——注意力机制详解 0. 前言1. 引入注意力机制2. 注意力机制2.1 注意力机制原理2.2 注意力机制分类 3. 添加注意机制的 Seq2Seq 模型3.1 数据处理3.2 模型构建与训练3.3 模型性能评估 小结系列链接 0. 前言 在传统的神经网络…...

架空防静电地板材质全解析:选对材质,守护精密空间的“安全卫士”

在现代科技驱动的社会中&#xff0c;无论是数据中心、实验室、手术室&#xff0c;还是高端电子厂房&#xff0c;静电都是精密设备的“隐形杀手”。而架空防静电地板作为这些场所的“安全卫士”&#xff0c;其材质选择直接决定了防静电性能、承重能力及使用寿命。今天&#xff0…...

Linux系统中部署java服务(docker)

1、不使用docker ✅ 1. 检查并安装 Java 环境 检查 Java 是否已安装&#xff1a; java -version✅ 2. 上传 Java 项目 JAR 文件 可以创建一个server文件夹&#xff0c;然后上传目录 查看当前目录 然后创建目录上传jar包 ✅ 3. 启动 Java 服务 java -jar hywl-server.jar…...

PyGame游戏开发(入门知识+组件拆分+历史存档/回放+人机策略)

前言&#xff1a; 本章实现游戏组件的复用解耦&#xff0c;以及使用配置文件替代原有硬编码形式&#xff0c;进而只需要改动配置文件即可实现整个游戏的难度和地图变化&#xff0c;同时增加历史记录功能&#xff0c;在配置文件开启后即可保存每一局的记录为json形式作为后续强化…...

【上位机——WPF】Window标签常用属性

常用属性 常用属性程序退出 常用属性都是写在Window标签中的 <Window x:Class"WpfDemo1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"…...

K8S Gateway AB测试、蓝绿发布、金丝雀(灰度)发布

假设有如下三个节点的 K8S 集群&#xff1a; ​ k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、场景分析 阅读本文&#xff0c;默认您已经安装了 K8S Gateway。 关于 AB 测试、金丝雀发布&#xff0c;可以看这篇文章。 二、实验准…...

人大金仓数据库 与django结合

要在Django项目中连接人大金仓数据库&#xff08;Kingbase&#xff09;&#xff0c;你需要使用一个适合的数据库适配器。人大金仓数据库是基于PostgreSQL的&#xff0c;因此你可以使用psycopg2库来与Django连接。但是&#xff0c;由于人大金仓数据库有其特定的功能和配置&#…...

RK3588 桌面系统配置WiFi和蓝牙配置

桌面右上角点击&#xff0c;打开选项&#xff0c;找到WiFi的选择网络或者WiFi设置 在弹出的窗口中选择需要连接的WiFi&#xff0c;然后右下角选择连接&#xff0c;然后输入WiFi密码即可连接。 25.4. 命令行连接wifi路由器 命令行配置wifi的方法有很多&#xff0c;下面介绍几种…...

TLV格式

‌TLV格式&#xff08;Tag-Length-Value&#xff09;是一种常用的数据序列化格式&#xff0c;主要用于数据包或消息的有效载荷编码。‌TLV格式将数据划分为三个主要部分&#xff1a;Tag&#xff08;标签&#xff09;、Length&#xff08;长度&#xff09;和Value&#xff08;值…...

2024年9月电子学会等级考试五级第三题——整数分解

题目 3、整数分解 正整数 N 的 K-P 分解是指将 N 写成 K 个正整数的 P 次方的和。本题就请你对任意给定的正整数 N、K、P&#xff0c;写出 N 的 K-P 分解。 时间限制&#xff1a;8000 内存限制&#xff1a;262144 输入 输入在一行给出 3 个正整数 N (≤ 400)、K (≤ N)、P (1 …...

软考 系统架构设计师系列知识点之杂项集萃(60)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;59&#xff09; 第97题 在面向对象设计中&#xff0c;&#xff08;&#xff09;可以实现界面控制、外部接口和环境隔离。&#xff08;&#xff09;作为完成用例业务的责任承担者&#xff0c;协调…...

使用Python开发经典俄罗斯方块游戏

使用Python开发经典俄罗斯方块游戏 在这篇教程中&#xff0c;我们将学习如何使用Python和Pygame库开发一个经典的俄罗斯方块游戏。这个项目将帮助你理解游戏开发的基本概念&#xff0c;包括图形界面、用户输入处理、碰撞检测等重要内容。 项目概述 我们将实现以下功能&…...

C++:字符数组与字符串指针变量的大小

#include<iostream> #include<cstring> int main(int argc, char const *argv[]) {// 字符数组char str[128] "hello world";std::cout<<sizeof(str)<<std::endl;std::cout<<strlen(str)<<std::endl;// 字符串指针变量char *st…...

stm32使用freertos时延时时间间隔不对,可能是晶振频率没设置

freertos 获取频率的接口 在 FreeRTOSConfig.h 文件中声明一个函数作为freertos的接口 /// /// brief 获取 SysTick 的频率 /// /// note arm cortex-m 系列 CPU 有一个 systick &#xff0c;里面有一个 CTRL 寄存器&#xff0c;其中的 bit2 /// 可以用来控制 systick 的时钟…...

51c~C语言~合集5

我自己的原文哦~ https://blog.51cto.com/whaosoft/13913911 一、大厂C语言编程10大规范 1 代码总体原则 1、清晰第一 清晰性是易于维护、易于重构的程序必需具备的特征。代码首先是给人读的&#xff0c;好的代码应当可以像文章一样发声朗诵出来。 目前软件维护期成本…...

前端流行框架Vue3教程:17. _组件数据传递

_组件数据传递 我们之前讲解过了组件之间的数据传递&#xff0c;props 和自定义事件 两种方式 props&#xff1a;父传子 自定义事件&#xff1a;子传父 除了上述的方案&#xff0c;props也可以实现子传父 一、项目结构 src/ └── components/├── ComponentsA.vue # 父…...

Stack overflow

本文来源 &#xff1a;腾讯元宝 Stack Overflow - Where Developers Learn, Share, & Build Careers 开发者学习&#xff0c;分享 通过学习、工作和经验积累等方式&#xff0c;逐步建立和发展自己的职业生涯。 Find answers to your technical questions and help othe…...

SpringBoot 3.4.5版本导入Lomobok依赖后无法生效的问题

问题背景 最近&#xff0c;随着DeepSeek的爆火&#xff0c;小编也编写了一个前后端分离的“知库随考”系统&#xff0c;由于Spring AI官方提示想要使用Spring AI的话要求Spring Boot的版本在“3.4.x”以上&#xff0c;所以我在创建SpringBoot项目的时候选择了了Server URL:http…...

FPGA: UltraScale+ bitslip实现(ISERDESE3)

收获 一晃五年~ 五年前那个夏夜&#xff0c;我对着泛蓝的屏幕敲下《给十年后的自己》&#xff0c;在2020年的疫情迷雾中编织着对未来的想象。此刻回望&#xff0c;第四届集创赛的参赛编号仍清晰如昨&#xff0c;而那个在家熬夜焊电路板的"不眠者"&#xff0c;现在…...

Electron详解:原理与不足

Electron是一个集成项目&#xff0c;它通过定制Chromium和Node.js&#xff0c;并将它们集成在内部来实现其功能。具体来说&#xff0c;Electron做了以下几个重要的工作&#xff1a; 定制Chromium&#xff1a;并将定制版本的Chromium集成在Electron内部。定制Node.js&#xff1…...

Spring Boot多数据源配置的陷阱与终极解决方案

引言 在微服务架构和复杂业务场景中&#xff0c;一个Spring Boot应用连接多个数据库的需求日益普遍。许多开发者尝试通过简单复制单数据源配置来实现多数据源&#xff0c;结果却遭遇了Bean冲突、事务失效、连接泄漏等隐蔽问题。本文将深入剖析Spring Boot自动配置的底层逻辑&a…...

android display 笔记(十四)VAU 和GSP 分别代表什么

VAU 和 GSP 的解释 GSP (Graphics/GPU Subsystem Processor) 含义&#xff1a; 图形处理子系统&#xff0c;通常指 SoC&#xff08;系统级芯片&#xff09;中负责 2D/3D 图形渲染、显示合成、图像后处理&#xff08;如缩放、旋转、色彩管理&#xff09; 的硬件模块。 在部分芯…...

tomcat 400 The valid characters are defined in RFC 7230 and RFC 3986

在遇到 Tomcat 因 URL 非法字符返回 400 Bad Request 时,选择在 Nginx 还是 Tomcat 中配置错误处理,需根据实际场景和需求权衡。以下是两种方案的详细对比及配置方法: 一、选择建议 方案适用场景优点缺点Nginx 配置- 需要统一处理所有后端服务(如多个 Tomcat 实例)的 400 …...

nginx负载均衡及keepalive高可用

实验前期准备&#xff1a; 5台虚拟机&#xff1a;4台当做服务器&#xff0c;1台当做客户机&#xff08;当然&#xff0c;也可以使用主机的浏览器&#xff09;&#xff0c;4台服务器中&#xff0c;2台服务器当做后端真实访问服务器&#xff1b;另外2台服务器当做负载均衡服务器…...

漏洞修复:tomcat 升级版本 spring-boot-starter-tomcat 的依赖项

在Spring Boot项目中修复Tomcat漏洞(如CVE-2024-21733)时,通常需要升级内嵌Tomcat版本。以下是具体操作步骤和注意事项: 一、确认当前Tomcat版本 通过启动日志查看 启动项目时,控制台日志中会显示类似 Starting Servlet engine: [Apache Tomcat/9.0.43] 的信息,直接查看版…...

二、IGMP

目录 1. IGMPv1 1.1 IGMPv1 报⽂类型 1.2 IGMPv1 工作机制 1.3 成员加入 1.4 离组机制 2. IGMPv2 2.1 IGMPv2 报文 2.3 查询器选举 & 维护 2.4 成员加入 2.4 离组机制 3. IGMPv3 3.1 IGMPv3 vs. IGMPv2 3.2 IGMPv3 报文 3.3 IGMPv3 工作机制 4. IGMP Proxy …...

Redis--基础知识点--27--redis缓存分类树

在 Redis 中存储分类树&#xff0c;通常需要选择合适的数据结构来表现层级关系。以下是使用 字符串&#xff08;String&#xff09; 和 哈希&#xff08;Hash&#xff09; 两种常见方案的举例说明&#xff0c;结合电商分类场景&#xff08;如 电子产品 > 手机 > 智能手机…...

【2025最新】VSCode Cline插件配置教程:免费使用Claude 3.7提升编程效率

 2025年最新VSCode Cline插件安装配置教程&#xff0c;详解多种免费使用Claude 3.7的方法&#xff0c;集成DeepSeek-R1与5大实用功能&#xff0c;专业编程效率提升指南。 Cline是VSCode中功能最强大的AI编程助手插件之一&#xff0c;它能与Claude、OpenAI等多种大模型无缝集…...

SQL笔记一

SQL的分类 DDL&#xff08;数据定义语言&#xff09;&#xff1a;CREATE&#xff08;创建&#xff09; ALTER&#xff08;修改&#xff09; DROP&#xff08;删除结构&#xff09; RENAME&#xff08;重命名&#xff09; TRUNCATE&#xff08;清空&#xff09; DML&#xff0…...

高可靠低纹波国产4644电源芯片在工业设备的应用

摘要 随着工业自动化和智能化的飞速发展&#xff0c;工业设备对于电源芯片的性能和可靠性提出了前所未有的严格要求。电源芯片作为工业设备的核心供电组件&#xff0c;其性能直接影响到整个设备的运行效率和稳定性。本文以国科安芯的ASP4644四通道降压稳压器为例&#xff0c;通…...

MyBatis 的分页插件 c

前言 大型项目的数据体量很大&#xff0c;在前端界面展示时为保障展示效果&#xff0c;会要求接口快速返回&#xff0c;这时候后端会选择分页获取数据&#xff0c;只传递要查询的页码数据。这就避免了大多问题&#xff0c;达到快速返回的效果。 常用的分页有2种&#xff1a; …...

网络安全-等级保护(等保) 2-5 GB/T 25070—2019《信息安全技术 网络安全等级保护安全设计技术要求》-2019-05-10发布【现行】

################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…...

嵌软面试每日一阅----FreeRTOS

一. FreeRTOS 创建任务的方法及区别 在 FreeRTOS 中&#xff0c;任务创建主要有两种方式&#xff1a;动态内存分配&#xff08;xTaskCreate()&#xff09;和静态内存分配&#xff08;xTaskCreateStatic()&#xff09;。以下是两者的核心区别及使用场景&#xff1a; 1. 动态创建…...

EasyExcel详解

文章目录 一、easyExcel1.什么是easyExcel2.easyExcel示例demo3.easyExcel read的底层逻辑~~4.easyExcel write的底层逻辑~~ 二、FastExcel1.为什么更换为fastExcel2.fastExcel新功能 一、easyExcel 1.什么是easyExcel 内容摘自官方&#xff1a;Java解析、生成Excel比较有名的…...

023-C语言预处理详解

C语言预处理详解 文章目录 C语言预处理详解1. 预定义符号2. #define定义常量3. #define定义宏4. 带有副作用的宏参数5. 宏替换的规则6. 宏函数的对比7. #和##7.1 #运算符7.2 ##运算符 8. 命名约定9. #undef10. 命令行定义11. 条件编译12. 头文件包含12.1 头文件被包含方式12.1.…...

C#自定义控件-实现了一个支持平移、缩放、双击重置的图像显示控件

1. 控件概述 这是一个继承自 Control 的自定义控件&#xff0c;主要用于图像的显示和交互操作&#xff0c;具有以下核心功能&#xff1a; 图像显示与缩放&#xff08;支持鼠标滚轮缩放&#xff09;图像平移&#xff08;支持鼠标拖拽&#xff09;视图重置&#xff08;双击重置…...

MarkitDown:AI时代的文档转换利器

在当今AI快速发展的时代,如何高效地将各种格式的文档转换为机器可读的格式,成为了一个迫切需要解决的问题。今天,我们来介绍一款由微软开发的强大工具——MarkitDown,它正是为解决这一问题而生的。 什么是MarkitDown? MarkitDown是一个用Python编写的轻量级工具,专门用…...

《数字分身进化论:React Native与Flutter如何打造沉浸式虚拟形象编辑》

React Native&#xff0c;依托JavaScript语言&#xff0c;借助其成熟的React生态系统&#xff0c;开发者能够快速上手&#xff0c;将前端开发的经验巧妙运用到移动应用开发中。它通过JavaScript桥接机制调用原生组件&#xff0c;实现与iOS和Android系统的深度交互&#xff0c;这…...

DeerFlow:字节新一代 DeepSearch 框架

项目地址&#xff1a;https://github.com/bytedance/deer-flow/ 【全新的 Multi-Agent 架构设计】独家设计的 Research Team 机制&#xff0c;支持多轮对话、多轮决策和多轮任务执行。与 LangChain 原版 Supervisor 相比&#xff0c;显著减少 Tokens 消耗和 API 调用次数&#…...

数字孪生工厂实战指南:基于Unreal Engine/Omniverse的虚实同步系统开发

引言&#xff1a;工业元宇宙的基石技术 在智能制造2025与工业元宇宙的交汇点&#xff0c;数字孪生技术正重塑传统制造业。本文将手把手指导您构建基于Unreal Engine 5.4与NVIDIA Omniverse的实时数字孪生工厂系统&#xff0c;集成Kafka实现毫秒级虚实同步&#xff0c;最终交付…...