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

WebRTC 的核心:RTCPeerConnection

WebRTC 的核心:RTCPeerConnection
  • WebRTC 的核心:RTCPeerConnection
    • 创建 RTCPeerConnection 对象
    • RTCPeerConnection 与本地音视频数据绑定
    • 媒体协商
    • ICE
      • 什么是 Candidate?
      • 收集 Candidate
      • 交换 Candidate
      • 尝试连接
    • SDP 与 Candidate 消息的互换
    • 远端音视频渲染
    • 参考

WebRTC 的核心:RTCPeerConnection

RTCPeerConnection 是 WebRTC API 中的一个对象,它提供了两个浏览器之间的实时通信。它使用音频、视频和数据流来进行点对点通讯,没有中介服务器的参与。这是一个极其有用的特性,使得实时通信变得更加高效和私密。

RTCPeerConnection的作用是在两个浏览器之间建立WebRTC通信通道。它使用ICE(Interactive Connectivity Establishment)协议决定浏览器之间的最佳路径来传输音频、视频和数据流。它让浏览器之间的网络连接变得简单、快捷和高效。
RTCPeerConnection API可以用于:

  1. 视频会议
  2. 实时游戏
  3. 文件共享
  4. 流媒体
  5. 实时语音聊天

创建 RTCPeerConnection 对象

语法:

new RTCPeerConnection()
new RTCPeerConnection(configuration)

参数 configuration 是一个 JSON 对象,用于提供配置新连接的选项。

在这里插入图片描述

  1. iceServers:一个由 RTCIceServer 对象组成的数组,每个对象描述一个可能被 ICE 代理使用的服务器。这些通常是 STUN 或 TURN 服务器。如果未指定,则将在没有可用的 STUN 或 TURN 服务器的情况下进行连接尝试,这将连接限制为本地对等点。
  2. iceTransportPolicy:当前的 ICE 传输策略。如果未指定策略,则默认使用 all 策略,允许考虑所有的候选。可能的值有:
    • “all”:所有的 ICE 候选都会被考虑。
    • “public”:只有拥有公共 IP 地址的 ICE 候选才会被考虑,已被移除。
    • “relay”:只有 IP 地址被中继的 ICE 候选,例如那些通过 STUN 或 TURN 服务器传递的,才会被考虑。
  3. bundlePolicy:指定当远程对等点与 SDP BUNDLE 标准不兼容时,应如何处理候选的协商。如果远程端点可以感知 BUNDLE,则在协商完成时,所有媒体轨道和数据通道都将捆绑到单个传输上,而不管使用何种策略,并且最初创建的任何多余传输都将在此时关闭。用技术术语来说,BUNDLE 允许两个对等点之间的所有媒体流流经单个 5 元组;也就是说,使用相同的传输协议从一个对等点的单个 IP 和端口到另一个对等点的单个 IP 和端口。如果假定为不平衡(balanced),这必须是以下字符串值之一:
    • “balanced”:ICE 代理最初为每一种内容类型(音频、视频、数据通道)创建一个 RTCDtlsTransport。如果远程端点无法感知 BUNDLE,那么每一个 DTLS 传输用于处理一种数据类型的通信。
    • “max-compat”:ICE 代理最初为每个媒体轨道创建一个 RTCDtlsTransport,对数据通道则创建一个单独的传输。如果远程端点无法感知 BUNDLE,那么对于所有的内容都会协商一个单独的 DTLS 传输。
    • “max-bundle”:ICE 代理最初仅创建一个 RTCDtlsTransport 来承载所有的 RTCPeerConnection 的数据。如果远程端点无法感知 BUNDLE,那么仅会协商一个轨道而忽略其余的轨道。
  4. rtcpMuxPolicy:收集 ICE 候选时使用的 RTCP mux 策略,以支持非复用的 RTCP。可能的值有:
    • “require”:告诉 ICE 代理仅收集 RTP 的 ICE 候选,并在它们之上多路复用 RTCP。如果远程对等点不支持 RTCP 多路复用,则会话协商失败。这是默认值。
    • “negotiate”:指示 ICE 代理收集 RTP 和 RTCP 候选。如果远程对等点支持 RTCP 复用,那么 RTCP 候选将在相应的 RTP 候选之上多路复用。否则,分别返回 RTP 和 RTCP 候选。
  5. peerIdentity:一个字符串,用于指定 RTCPeerConnection 目标对等点的标识。如果设置了该值(其默认为 null),则在成功验证远程对等点的身份为给定的名称之前,RTCPeerConnection 不会与其建立连接。
  6. certificates:一个由 RTCCertificate 对象组成的数组,用于连接的身份验证。如果未指定该属性,则会为每一个 RTCPeerConnection 实例自动创建一组证书。尽管一个给定的连接只使用一个证书,但提供多个证书可以支持多种算法,从而提高某些情况下的连接成功的机率。此配置选项在首次指定后便不能更改;一旦设置了证书,此属性将在之后调用 RTCPeerConnection.setConfiguration() 时被忽略。
  7. iceCandidatePoolSize:一个无符号 16 位整数,其指定了预获取的 ICE 候选池的大小。其默认值为 0(表示不会发生候选的预获取)。如果这个值发生变化了,那么会重新收集候选者。

RTCPeerConnection 与本地音视频数据绑定

RTCPeerConnection 提供2种方法进行数据绑定:addTrack() 和 addStream()。

其中 addStream() 已经被 WebRTC 标记为过时,因此建议使用 addTrack() 方法。

当客户端从服务端接收到 joined 消息后,它会创建 RTCPeerConnection 对象,然后调用 bindTrack() 函数将其与之前通过 getUserMedia() 采集到的音视频数据绑定:

function bindTrack() {...ls.getTracks().foreach((track) => {pc.addTrack(track, ls);...})...
}

其中,ls 是一个全局变量,当通过 getUserMedia() 采集到 MediaStream 后,需要将其交由 ls 管理;pc 是 RTCPeerConnection 的缩写,也是一个全局变量,当 RTCPeerConnection 创建好后,交由 pc 管理。

媒体协商

当 RTCPeerConnection 对象与音视频数据绑定后,紧接着需要进行媒体协商。看双方都支持那些编码方式,支持哪些分辨率等。协商的方法是通过信令服务器交换媒体能力信息,交换的内容是 SDP 格式的。

在 WebRTC 中,媒体协商是有严格的协商顺序的,如下图所示:

在这里插入图片描述

整个过程分为 8 步:

  1. Amy 调用 createOffer 方法创建 offer 消息。offer 消息中的内容是 Amy 的 SDP 信息。
  2. Amy 调用 setLocalDescription 方法,将本端的 SDP 信息保存起来。
  3. Amy 将 offer 消息通过信令服务器传给 Bob。
  4. Bob 收到 offer 消息后,调用 setRemoteDescription 方法将其存储起来。
  5. Bob 调用 createAnswer 方法创建 answer 消息, 同样,answer 消息中的内容是 Bob 的 SDP 信息。
  6. Bob 调用 setLocalDescription 方法,将本端的 SDP 信息保存起来。
  7. Bob 将 anwser 消息通过信令服务器传给 Amy。
  8. Amy 收到 anwser 消息后,调用 setRemoteDescription 方法,将其保存起来。

通过以上步骤就完成了通信双方媒体能力的交换。

ICE

当媒体协商完成后,WebRTC 就开始建立网络连接了,其过程叫 ICE(Interactive Connectivity Establishment,交互式连接建立)。更确切地说,ICE 是在各端调用 setRemoteDescription 方法后就开始了。其操作过程如下:

  1. 收集 Candidate
  2. 交换 Candidate
  3. 按优先级尝试连接
什么是 Candidate?

Candidate 是 WebRTC API 的接口之一,表示用于建立 RTCPeerConnection 的候选交互连接建立(ICE)的配置信息。它是至少包含 {address, port, protocol} 三元组的一个信息集。

RTCIceCandidate 实例属性:

  1. candidate:表示用于连接检查的候选者的传输地址的字符串。
    格式为:a=candidate:{foundation} {component} {protocol} {priority} {ip} {port} typ {type} generation {generation} ufrag {username} network_id {id} network_cost {cost}。
    以如下 candidate 为例说明其代表的含义:a=candidate:1221703924 1 udp 2122260223 192.168.0.105 51417 typ host generation 0 ufrag Q8Wv network-id 1 network-cost 10。
    typ host 表示本地候选者,使用的 IP 是 192.168.0.105,端口为 51417,使用 UDP 协议,其优先级为 2122260223,generation 表示代数,初始值为 0,用户名为 Q8Wv,如果更新 candidate 则 generation 值会递增,替换老的 candidate。
  2. sdpMid:表示候选者的媒体流标识标签的字符串,该标签在候选者关联的组件中唯一标识媒体流,如果不存在这样的关联,则为 null。
  3. sdpMLineIndex:如果值不为 null,sdpMLineIndex 表示 SDP 中候选者关联的从零开始的媒体描述索引编号。

其他更多属性见于:RTCIceCandidate

WebRTC 还将 Candidate 分为了四种类型:host、srflx、prflx、relay,它们的优先级依次递减。假如 WebRTC 收集到两个 Candidate,一个是 host 类型,另一个是 relay 类型,那么 WebRTC 会先尝试与 host 类型的 Candidate 建立连接,如果不成功,才会使用 relay 类型的 Candidate。

收集 Candidate

WebRTC 收集 Candidate 时有几种途径:

  1. host 类型的 Candidate 由主机的网卡个数决定。一般一个网卡对于一个 IP 地址,每个 IP 地址随机分配一个端口从而生成一个 host 类型的 Candidate;
  2. srflx 类型的 Candidate 由 STUN 服务器获得的 IP 地址和端口生成;
  3. relay 类型的 Candidate 由 TRUN 服务器获得的 IP 地址和端口生成。

收集到 Candidate 后,为了通知上层,WebRTC 还在 RTCPeerConnection 对象中提供了 onicecandidate 事件。为了将收集到的 Candidate 交换给对端,需要为 onicecandidate 事件设置一个回调函数:

pc.onicecandidate = (e) => {if (e.candidate) {...}
}

通过该回调函数就可以获得 WebRTC 底层收集到的所有 Candidate 了。同时,还可以在函数内实现发送给对端的操作。

交换 Candidate

WebRTC 收集 Candidate 后,会通过信令系统将它们发送给对端。对端接收后,会与本地的 Candidate 形成 CandidatePair(连接候选者对)。

有了 CandidatePair,WebRTC 就可以开始尝试建立连接了。

注意,Candidate 的交换不是等所有 Candidate 收集好了再进行的,而是边收集边交换。

尝试连接

当 WebRTC 形成 CandidatePair 后,便开始尝试进行连接。一旦发现一个可以连通的 CandidatePair 时,就不再进行其他的连接尝试了,但发现新的 Candidate 时仍然可以继续交换。

SDP 与 Candidate 消息的互换

媒体协商和 ICE 都需要通信双方做信息的交换,如交换 SDP 和 Candidate。这种信息交换使用的也是信令系统,只不过需要为这种需求专门设置一个新的信令,即 message。

信息交换的过程:

  1. 发起方向信令服务器发送 message;
  2. 服务器收到 message 后不做任何处理,直接转发给目标用户;
  3. 目标用户接收 message。

客户端发送消息:

function sendMsg(roomid, data) {...socket.emit('message', roomid, data);
}

服务器转发:

socket.on('message', (room, data) => {socket.to(room).emit('message', room, data);
});

客户端接收:

socket.on('message', (room, data) => {...if (data.hasOwnProperty('type') && data.type === 'offer') {...} else if (data.hasOwnProperty('type') && data.type === 'answer') {...} else if (data.hasOwnProperty('type') && data.type === 'candidate') {...} else {...}
});

远端音视频渲染

当各端将收集到的 Candidate 通过信令系统交换给对方后,WebRTC 内部就开始就开始尝试建立连接了。连接一旦建成,音视频数据就开始源源不断地由发送端发送给接收端。

每当有远端的音视频数据传过来时,RTCPeerConnection 对象的 ontrack() 事件就会被触发。因此只需要给 ontrack() 事件设置一个回调函数,就可以拿到远端的 MediaStream 了。再将远端音视频流赋值给本地 标签的 srcObject 属性,就可以播放音视频数据了。

具体代码如下所示:

function getRemoteStream(mediaStream) {...// 将远端音视频流赋值给本地 <video> 标签的 srcObject 属性videoElement.srcObject = mediaStream;
}
let pc = new RTCPeerConnection(...);
...
pc.ontrack = getRemoteStream;
...

参考

  1. https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection
  2. https://www.cnblogs.com/ssyfj/p/14811253.html
  3. https://webrtc.org.cn/webrtc-tutorial-2-signaling-stun-turn/

相关文章:

WebRTC 的核心:RTCPeerConnection

WebRTC 的核心&#xff1a;RTCPeerConnection WebRTC 的核心&#xff1a;RTCPeerConnection 创建 RTCPeerConnection 对象RTCPeerConnection 与本地音视频数据绑定媒体协商ICE 什么是 Candidate&#xff1f;收集 Candidate交换 Candidate尝试连接 SDP 与 Candidate 消息的互换…...

Spring Boot 中 WebClient 的实践详解

在现代微服务架构中&#xff0c;服务之间的通信至关重要。Spring Boot 提供了 WebClient&#xff0c;作为 RestTemplate 的替代方案&#xff0c;用于执行非阻塞式的 HTTP 请求。本文将详细讲解 WebClient 的实践&#xff0c;包括配置、使用场景以及常见的优化策略&#xff0c;帮…...

OceanBase 社区版 4.0 离线方式升级bp1至bp2 指南(含避坑总结)

注&#xff1a;目前社区版对 4.0 升级 bp1至 bp2也未有完善的文档&#xff0c;本次升级中也是遇到不少坑&#xff0c;写本文也希望对OB感兴趣的可以尝试少些遇坑。 也希望对升级有更好方式建议方式的朋友一起切磋交流&#xff0c;以便再进一步完善升级方案。 第一次做OB的升级&…...

@ControllerAdvice 的实现原理

从源码角度分析 Spring Boot 中 ControllerAdvice 的实现原理 在 Spring Boot 开发中&#xff0c;ControllerAdvice 是一个非常强大的特性&#xff0c;允许开发者集中处理控制器中的异常、全局数据绑定和模型属性。本文将从源码的角度探讨 ControllerAdvice 的实现原理&#x…...

将当前cad图中实体复制到另一个新的dwg的块中,并插入块——CAD c#实现

本案例为&#xff1a;将当前cad图中实体复制到另一个cad的块中&#xff0c;并插入块。 目前代码尚未调试成功&#xff0c;找bug中...... public class Demo {[CommandMethod("xx1")]public void XXA(){// 获取当前文档和数据库Document currentDoc Application.Doc…...

MongoDB-ObjectID 生成器

前言 MongoDB中一个非常关键的概念就是 ObjectID&#xff0c;它是 MongoDB 中每个文档的默认唯一标识符。了解 ObjectID 的生成机制不仅有助于开发人员优化数据库性能&#xff0c;还能帮助更好地理解 MongoDB 的设计理念。 什么是 MongoDB ObjectID&#xff1f; 在 MongoDB …...

解决Vue项目打包后dist中的index.html用浏览器直接打开显示空白页或者page not found的问题

前言 默认情况下&#xff0c;使用 npm run build 打包后的 index.html 无法直接访问&#xff0c;需要nginx转发或使用node启用简单http serve等方式实现。 实际开发中&#xff0c;有时需临时打开前端项目&#xff0c;若可以直接打开打包后的文件&#xff0c;对某些场景下他人简…...

爬虫基础之Session和Cookie

在浏览网站的过程中&#xff0c;我们经常会遇到需要登录的情况&#xff0c;有些页面只有登录之后才可以访问。在登录之后可以连续访问很多次网站&#xff0c;但是有时候过一段时间就需要重新登录。还有一些网站&#xff0c;在打开浏览器时就自动登录了,而且在很长时间内都不会失…...

计算机毕业设计PyFlink+Hadoop广告推荐系统 广告预测 广告数据分析可视化 广告爬虫 大数据毕业设计 Spark Hive 深度学习 机器学

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

排序算法(2):选择排序

问题 排序 [30, 24, 5, 58, 18, 36, 12, 42, 39] 选择排序 选择排序每次从待排序序列中选出最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放到序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素中继续寻找最小&#xff08;或最大&#xff09;元素…...

uni-app(HBuilderX)搭建小程序流程(请求封装,下拉刷新,底部加载等)

uni-app 是一个跨平台的前端框架&#xff0c;用于开发多端应用。uni-app 提供了一个统一的 API&#xff0c;允许开发者编写一次代码&#xff0c;最终部署到多个平台&#xff0c;极大地提高了开发效率。在编写小程序的时候和原生微信开发者工具语法略有区别。 目录 一、请求工具…...

【Super Tilemap Editor使用详解】(一):创建图块集

1、在场景中创建瓦片地图之前&#xff0c;我们需要先创建一个图块集供地图使用。 可以在“Project”面板中创建&#xff1a; 也可以在Assets“” 菜单中创建&#xff1a; 2、创建成功之后&#xff0c;“Atlas Texture”是空的&#xff0c;我们需要选择一个图集。 3、选中插件中…...

驱动---1.DAC8552实现三角波输出

最近开始进行新项目的研发&#xff0c;考虑用DAC做一个前级输出&#xff0c;选择了DAC8552这个器件的一个模块&#xff0c;用了野火的指南者做主控&#xff0c;芯片是STM32F103VET6&#xff0c;主频是72MHz。 一、器件手册重要信息提取 1.DAC8552具有十六位的分辨率、双通道输…...

PHP中GD库的使用

由于我要用到php的验证码 <?php session_start();// 生成验证码 $random_code substr(md5(uniqid(mt_rand(), true)), 0, 6);// 将验证码保存到 session 中 $_SESSION[captcha] $random_code;// 创建图片 $font 6; $image_width 100; $image_height 40;// 创建图像 $…...

【ChArUco Marker】标定板检测

目录 1.ChArUco介绍2.源码分析&#xff08;opencv 4.5.4&#xff09;3.ChAruco板创建&#xff08;opencv 4.5.4&#xff09;4.Charuco板检测&#xff08;opencv 4.5.4&#xff09;ChArUco检测源码&#xff08;不使用标定参数&#xff09; 5.ChArUco姿态估计&#xff08;opencv …...

Kafka | RabbitMQ | RocketMQ | ActiveMQ 的区别和入门案例

springboot&#xff0c;vue&#xff0c;springcloudalibaba课程视频&#xff0c;有需要可以看看 <!-- springboot&#xff0c;springboot整合redis&#xff0c;整合rocketmq视频&#xff1a; --> https://www.bilibili.com/video/BV1nkmRYSErk/?vd_source14d27ec13a473…...

TensorBoard

1、TensorFlow的TensorBoard TensorBoard是TensorFlow的一个组件&#xff0c;它提供了一个交互式的界面&#xff0c;用于可视化TensorFlow程序的训练过程和模型结构。 使用TensorBoard&#xff0c;你可以&#xff1a; 可视化训练过程中的各种指标&#xff0c;如损失函数、准…...

C# 中的异步编程:提升应用程序响应性和性能

C#中的异步编程&#xff08;Asynchronous Programming&#xff09;。异步编程是现代应用程序开发中非常重要的一个方面&#xff0c;它允许程序在等待长时间运行的操作&#xff08;如I/O操作、网络请求等&#xff09;时继续执行其他任务&#xff0c;从而提高应用程序的响应性和性…...

前端框架 React 与 Vue3对比 —— 技术选型

在进行前端框架React与Vue3的技术选型对比时&#xff0c;我们可以从以下几个方面进行综合考虑&#xff1a; 1. 性能比较 • Vue3 通过 Vite 打包工具实现了快速的开发和构建&#xff0c;同时使用了响应式系统和 Proxy 技术来提高数据响应速度。在大部分测试用例中&#xff0c;…...

虚拟机与Xshell5和Xftp4连接与虚拟机克隆

虚拟机与Xshell5和Xftp4连接与虚拟机克隆 虚拟机与Xshell5和Xftp4连接 虚拟机与Xshell5连接 下载Xshell5后启动出现如下界面&#xff0c;点击新建 新建会话输入虚拟机命名&#xff0c;如master&#xff0c;主机输入虚拟机IP&#xff0c;xxx.xxx.xxx.xxx然后确认&#xff0c;…...

华为USG系列防火墙 RESTCONF NAT配置 Python实现

目录 前言 文档下载 开启RESTCONF接口 Python 实现SNAT增删改查 查看nat映射列表 查看私网地址池 查看源地址池&#xff08;公网&#xff09; 查看nat映射规则 创建nat映射规则 创建私网地址池 创建源地址池 创建nat映射规则 修改NAT映射规则 删除NAT映射规则 …...

qemu安装arm64架构银河麒麟

qemu虚拟化软件&#xff0c;可以在一个平台上模拟另一个硬件平台&#xff0c;可以支持多种处理器架构。 一、安装 安装教程&#xff1a;https://blog.csdn.net/qq_36035382/article/details/125308044 下载链接&#xff1a;https://qemu.weilnetz.de/w64/2024/ 我下载的是 …...

深入解析 Spring 框架:核心特性与应用价值

1.什么是spring? Spring 是一个开源的 Java 应用框架&#xff0c;由 Pivotal Software 提供支持。它为开发基于 Java 的企业级应用提供了一整套基础设施支持。Spring 框架的核心功能是依赖注入&#xff08;Dependency Injection, DI&#xff09;&#xff0c;它帮助开发者实现…...

protobuf 报文编解码工具

QT实现的 protobuf 反序列化 & 序列化工具&#xff0c;版本号V1.2 下载链接&#xff1a;protobuf报文编解码工具资源-CSDN文库 源码github&#xff1a;ProtobufTool 使用说明: 1. 点击“加载proto文件”按钮&#xff0c;从本地选择 .proto文件 2. 选择消息名称&#xff…...

Milvus向量数据库06-RAG检索增强

Milvus向量数据库06-RAG检索增强 文章目录 Milvus向量数据库06-RAG检索增强1-学习目标2-参考网址3-执行过程记录1-到底什么是RAGRAG 的基本流程&#xff1a;为什么 RAG 优于传统的基于检索的方法&#xff1a;示例流程&#xff1a; 2-RAG和Elasticsearch对比3-RAG和向量数据库之…...

Unity3D下采集camera场景并推送RTMP服务实现毫秒级延迟直播

技术背景 好多开发者&#xff0c;希望我们能够分享下如何实现Unity下的camera场景采集并推送rtmp服务&#xff0c;然后低延迟播放出来。简单来说&#xff0c;在Unity 中实现采集 Camera 场景并推送RTMP的话&#xff0c;先是获取 Camera 场景数据&#xff0c;通过创建 RenderTe…...

标记数据集生成模型助力无数据情况下的大模型指令微调

在构建大模型应用时&#xff0c;通常有两种方式来改进效果&#xff0c;一种是构建外部知识库&#xff0c;利用RAG来完成。但RAG并不是万能的&#xff0c;对于特定领域的LLM应用&#xff0c;以及无需示例&#xff0c;就能完成特定任务等场合就需要进行微调。然而&#xff0c;微调…...

第六届地博会世界酒中国菜助力广州龙美地标美食公司推动地标发展

第六届知交会暨地博会&#xff1a;世界酒中国菜助力广州龙美地标美食公司推动地标产品创新发展 2024年12月9日至11日&#xff0c;第六届粤港澳大湾区知识产权交易博览会暨国际地理标志产品交易博览会在中新广州知识城盛大启幕。本届盛会吸引了全球众多知识产权领域的专业人士和…...

vue响应式原理

对于响应式原理&#xff0c;我们先了解vue是一个MVVM结构的框架&#xff1b;也就是数据层、视图层、数据-视图层&#xff1b;响应式的原理就是实现当数据更新时&#xff0c;视图层也要相应的更新&#xff0c;基于响应式原理我们可以使数据驱动视图的实现变得简单而高效 一、响…...

SwiftUI 列表(或 Form)子项中的 Picker 引起导航无法跳转的原因及解决

概述 在 SwiftUI 的界面布局中&#xff0c;列表&#xff08;List&#xff09;和 Form 是我们秃头码农们司空见惯的选择。不过大家是否知道&#xff1a;如果将 Picker 之类的视图嵌入到列表或 Form 的子项中会导致导航操作无法被触发。 从上图可以看到&#xff1a;当在 List 的…...

使用Allure作为测试报告生成器(Java+Selenium)

背景 JAVA项目中原先用Jenkinsseleniumselenium grid来日常测试UI并记录。 问题 当某一个testSuite失败时&#xff0c;当需要确认UI regression issue还是selenium test case自身的问题&#xff0c;需要去jenkins中查log&#xff0c;一般得到的是“Can not find element xxx…...

【论文阅读】处理器芯片敏捷设计方法:问题与挑战

作者&#xff1a;包云岗老师 包云岗老师是计算机体系结构方向的大牛&#xff0c;推动了体系结构方面的开源事业! 欢迎对本栏目感兴趣的人学习"一生一芯"~ 学习体会&#xff1a; 已有的软硬件生态系统和开发成本制约了对新结构的探索。但目前仍在几种路线上做尝试~ 1…...

系统内核自动处理 TCP 连接(自动发送 RST 数据包来重置连接)

使用原始套接字发送了一个 SYN 数据包后&#xff0c;对方发送了 SYN,ACK 数据包&#xff0c;但系统仍然会自动发送 RST 数据包。这通常是因为操作系统内核在处理 TCP 连接时的行为。 原因分析 内核处理 TCP 连接&#xff1a; 即使你使用了原始套接字来发送和接收数据包&#x…...

VLDB 2024 | 时空数据(Spatial-temporal)论文总结

VLDB 2024于2024年8月26号-8月30号在中国广州举行。 本文总结了VLDB 2024有关时空数据&#xff08;time series data&#xff09;的相关论文&#xff0c;主要包含如有疏漏&#xff0c;欢迎大家补充。 &#x1f31f;【紧跟前沿】“时空探索之旅”与你一起探索时空奥秘&#xf…...

以ATTCK为例构建网络安全知识图

ATT&CK&#xff08;Adversarial Tactics, Techniques, and Common Knowledge &#xff09;是一个攻击行为知识库和模型&#xff0c;主要应用于评估攻防能力覆盖、APT情报分析、威胁狩猎及攻击模拟等领域。本文简单介绍ATT&CK相关的背景概念&#xff0c;并探讨通过ATT&a…...

Qt初识_对象树

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Qt初识_对象树 收录于专栏【Qt开发】 本专栏旨在分享学习Qt的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 什么是对象树 为什么要引…...

规范秩相关信息搜集Day2

系列博客目录 文章目录 系列博客目录1.A Survey on Tensor Techniques and Applications in Machine Learning2.有没有研究低秩矩阵有利于分类的计算机方面的论文呢3.Image classification based on low-rank matrix recovery and Naive Bayes collaborative representatio 基于…...

【unity小技巧】分享vscode如何进行unity开发,且如何开启unity断点调试模式,并进行unity断点调试(2024年最新的方法,实测有效)

文章目录 前言一、前置条件1、已安装Visual Studio Code&#xff0c;并且unity首选项>外部工具>外部脚本编辑器选择为Visual Studio Code [版本号]&#xff0c;2、在Visual Studio Code扩展中搜索Unity&#xff0c;并安装3、同时注意这个插件下面的描述&#xff0c;需要根…...

交换瓶子(图论 贪心)

1224. 交换瓶子 - AcWing题库 把每一个瓶子看成一个点&#xff0c;从每个瓶子向他应该在的那个位置的瓶子连一条边 通过这个方式&#xff0c;我们就可以连出n条边 观察可以发现这些图有特点&#xff1a; n个点 连成n条边 因为每个点会指向它应该在的位置的那个点&#xff…...

汽车升级到底应不应该设置“可取消“功能

最近&#xff0c;汽车OTA&#xff08;Over-the-Air&#xff09;升级频频成为车主讨论的热点。有些车主反映&#xff0c;一些升级增加了实用功能&#xff0c;而另一些却让体验变得复杂甚至带来不便。于是&#xff0c;大家不禁发问&#xff1a;汽车升级功能究竟应不应该允许“可取…...

Mac电脑钓鱼到拿下核心权限

目录 一. 前言 二. PKG后门制作阶段 2.1 环境准备 2.2 制作过程 2.3 成功上线 三 . 浏览器密码抓取 四. 权限维持 1. 手动权限维持 2. MSF自动化维持 五. 参考文章 一. 前言 攻防对抗强度和难度日益演进,传统的渗透测试思路成本逐渐提高,钓鱼已经成为当下攻击者最常…...

Docker多架构镜像构建踩坑记

背景 公司为了做信创项目的亮点&#xff0c;需要将现有的一套在X86上运行的应用系统迁移到ARM服务器上运行&#xff0c;整个项目通过后端Java&#xff0c;前端VUEJS开发通过CICD做成Docker镜像在K8S里面运行。但是当前的CICD产品不支持ARM的镜像构建&#xff0c;于是只能手工构…...

docker 架构详解

Docker架构是基于客户端-服务器&#xff08;C/S&#xff09;模式的&#xff0c;包含多个关键组件&#xff0c;以确保容器化应用的高效构建、管理和运行。以下是对Docker架构的详细解析&#xff1a; Docker 架构概述 Docker 架构采用客户端-服务器&#xff08;C/S&#xff09;…...

05-标准库开发-STM32-IIC协议

七、STM32中IIC协议 概述 Inter-Integrated Circuit (IIC)&#xff0c;也常称为I2C&#xff08;I squared C&#xff09;&#xff0c;是一种同步、串行、半双工通信总线协议。它主要用于连接低速外围设备到处理器或微控制器上&#xff0c;如MPU6050姿态传感器、OLED显示屏、存…...

vue 封装全局过滤器

1.找到utils下创建fifilter.js 一些常用的过滤方法 export const filters {//url解码urlCode: value > {if (!value) return let v decodeURIComponent(value)let bigIndex v.lastIndexOf(/)let endIndex v.lastIndexOf(.)let url v.substring(bigIndex 1, endIndex)…...

【PlantUML系列】流程图(四)

目录 目录 一、基础用法 1.1 开始和结束 1.2 操作步骤 1.3 条件判断 1.4 并行处理 1.5 循环 1.6 分区 1.7 泳道 一、基础用法 1.1 开始和结束 开始一般使用start关键字&#xff1b;结束一般使用stop/end关键字。基础用法包括&#xff1a; start ... stopstart ...…...

MATLAB中的合并分类数组

目录 创建分类数组 串联分类数组 创建具有不同类别的分类数组 串联具有不同类别的数组 分类数组的并集 此示例演示了如何合并两个分类数组。 创建分类数组 创建分类数组 A&#xff0c;其中包含教室 A 中的 25 个学生的首选午餐饮料。 rng(default) A randi(3,[25,1]); …...

流编辑器sed(stream editor)

一.sed简介 sed是一种流编辑器&#xff0c;处理时&#xff0c;把当前处理的行存储在临时缓冲区中&#xff0c;称为模式空间&#xff0c;接着用sed命令处 理缓冲区中的内容&#xff0c;处理完成后&#xff0c;把缓冲区的内容送往屏幕。接着处理下一行&#xff0c;这样不断重复&…...

R语言的数据结构--矩阵

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言医学数据分析实践-R语言的数据结构-CSDN博客 矩阵是一个二维数组&#xff0c;矩阵中的元素都具有相…...

使用 Python 爬取某网站简历模板(bs4/lxml+协程)

使用 Python 爬取站长素材简历模板 简介 在本教程中&#xff0c;我们将学习如何使用 Python 来爬取站长素材网站上的简历模板。我们将使用requests和BeautifulSoup库来发送 HTTP 请求和解析 HTML 页面。本教程将分为两个部分&#xff1a;第一部分是使用BeautifulSoup的方法&am…...