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

WebRTC服务质量(09)- Pacer机制(01) 流程概述

WebRTC服务质量(01)- Qos概述
WebRTC服务质量(02)- RTP协议
WebRTC服务质量(03)- RTCP协议
WebRTC服务质量(04)- 重传机制(01) RTX NACK概述
WebRTC服务质量(05)- 重传机制(02) NACK判断丢包
WebRTC服务质量(06)- 重传机制(03) NACK找到真正的丢包
WebRTC服务质量(07)- 重传机制(04) 接收NACK消息
WebRTC服务质量(08)- 重传机制(05) RTX机制
WebRTC服务质量(09)- Pacer机制(01) 流程概述
WebRTC服务质量(10)- Pacer机制(02) RoundRobinPacketQueue
WebRTC服务质量(11)- Pacer机制(03) IntervalBudget
WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据

一、前言:

Pacer 是一种数据发送调度机制。它的主要功能是根据网络带宽限制、网络拥塞控制的反馈以及媒体的发送策略,对数据包的发送进行适配和节奏调度,以避免网络拥塞、减少丢包并保证流媒体传输的平滑性。

二、核心概念:

2.1 Pacer 的作用:

  • 流量平滑:音频、视频等媒体数据包可能在生成时间上分布不均,通过 Pacer,可以将这些数据包的发送节奏调整成更均匀的形式,避免突发流量冲击网络。
  • 速率控制:Pacer 会根据传输码率(由拥塞控制算法提供,例如 Google 的 Congestion Control),动态调整包的发送速率,确保发送端不超过网络容量。
  • 优先级处理:Pacer 支持区分不同的流类型(例如音频、视频、FEC 冗余流等),为高优先级流(如音频)留出更多资源或者保证其更低的延迟。

2.2 Pacer 的工作流程:

  1. 音视频流媒体按照编码器的设定发送数据包。
  2. 数据包会先进入一个队列(Packet Queue)。
  3. Pacer 通过定时器或事件驱动机制,根据当前允许的发送速率(由拥塞控制模块动态提供)从队列中提取数据包发送。
  4. 如果发送速率受限,多余的包会继续留在队列中等待下一轮调度。

以下是简化的机制模型:

[Media Encoder] -> [Packet Queue] -> Pacer -> [Network Sender]

三、核心代码:

先想想,根据前面的概念阐述,如果要让你写,你怎么写呢?是不是重点实现以下几个模块:

  • packet_router.h/cpp:负责将数据包分发到具体的网络发送端。
  • packet_sender.h/cpp:实现了调度核心逻辑。
  • packet_queue.h/cpp:实现用于存储待发送数据包的队列。

现在具体看看webrtc如何做的。

3.1、Pacer对象创建:

  • PeerConnection当中创建Call对象;

    // 从上到下调用顺序如下:
    PeerConnectionFactory::CreatePeerConnectionOrError -->
    PeerConnectionFactory::CreateCall_w -->
    CallFactory::CreateCall --> 
    Call::Create
    
  • Call对象创建RtpTransportControllerSend:

    创建Call时候首先得创建Call::Config,便于以后创建Pacer对象时候作为参数;

    Call* Call::Create(const Call::Config& config,Clock* clock,rtc::scoped_refptr<SharedModuleThread> call_thread,std::unique_ptr<ProcessThread> pacer_thread) {RTC_DCHECK(config.task_queue_factory);return new internal::Call(clock, config,std::make_unique<RtpTransportControllerSend>(clock, config.event_log, config.network_state_predictor_factory,config.network_controller_factory, config.bitrate_config,std::move(pacer_thread), config.task_queue_factory, config.trials),std::move(call_thread), config.task_queue_factory);
    }
    

    这儿的config.trials,会导致后面创建PacedSender对象的时候,处理模式为kPeriodic,也就是周期处理模式;

  • RtpTransportControllerSend创建PacerSender对象:

    RtpTransportControllerSend 是 WebRTC 中负责发送侧 RTP 流量控制的核心模块。它是 RTP 传输的控制器,负责管理和协调发送侧的各种功能,包括比特率管理(带宽估算 BWE)、节奏控制(Pacer)、网络状态预测和反馈处理等。我们先看看构造函数:

    RtpTransportControllerSend::RtpTransportControllerSend(Clock* clock,webrtc::RtcEventLog* event_log,NetworkStatePredictorFactoryInterface* predictor_factory,NetworkControllerFactoryInterface* controller_factory,const BitrateConstraints& bitrate_config,std::unique_ptr<ProcessThread> process_thread,TaskQueueFactory* task_queue_factory,const WebRtcKeyValueConfig* trials): clock_(clock),event_log_(event_log),bitrate_configurator_(bitrate_config),process_thread_started_(false),process_thread_(std::move(process_thread)),use_task_queue_pacer_(IsEnabled(trials, "WebRTC-TaskQueuePacer")),process_thread_pacer_(use_task_queue_pacer_? nullptr: new PacedSender(clock,&packet_router_,event_log,trials,process_thread_.get())),task_queue_pacer_(use_task_queue_pacer_? new TaskQueuePacedSender(clock,&packet_router_,event_log,trials,task_queue_factory,/*hold_back_window = */ PacingController::kMinSleepTime): nullptr),observer_(nullptr),controller_factory_override_(controller_factory),controller_factory_fallback_(std::make_unique<GoogCcNetworkControllerFactory>(predictor_factory)),process_interval_(controller_factory_fallback_->GetProcessInterval()),last_report_block_time_(Timestamp::Millis(clock_->TimeInMilliseconds())),reset_feedback_on_route_change_(!IsEnabled(trials, "WebRTC-Bwe-NoFeedbackReset")),send_side_bwe_with_overhead_(!IsDisabled(trials, "WebRTC-SendSideBwe-WithOverhead")),add_pacing_to_cwin_(IsEnabled(trials, "WebRTC-AddPacingToCongestionWindowPushback")),relay_bandwidth_cap_("relay_cap", DataRate::PlusInfinity()),transport_overhead_bytes_per_packet_(0),network_available_(false),retransmission_rate_limiter_(clock, kRetransmitWindowSizeMs),task_queue_(task_queue_factory->CreateTaskQueue("rtp_send_controller",TaskQueueFactory::Priority::NORMAL)) {ParseFieldTrial({&relay_bandwidth_cap_},trials->Lookup("WebRTC-Bwe-NetworkRouteConstraints"));initial_config_.constraints = ConvertConstraints(bitrate_config, clock_);initial_config_.event_log = event_log;initial_config_.key_value_config = trials;RTC_DCHECK(bitrate_config.start_bitrate_bps > 0);pacer()->SetPacingRates(DataRate::BitsPerSec(bitrate_config.start_bitrate_bps), DataRate::Zero());if (absl::StartsWith(trials->Lookup("WebRTC-LazyPacerStart"), "Disabled")) {EnsureStarted();}
    }
    

    我们分段看下,主要分为四大步:

    (1) Pacer 类型选择

    构造函数根据配置决定使用 TaskQueuePacedSender 或传统的 PacedSender

    use_task_queue_pacer_(IsEnabled(trials, "WebRTC-TaskQueuePacer")),
    process_thread_pacer_(use_task_queue_pacer_? nullptr: new PacedSender(clock, &packet_router_, event_log, trials, process_thread_.get())),
    task_queue_pacer_(use_task_queue_pacer_? new TaskQueuePacedSender(clock, &packet_router_, event_log, trials,task_queue_factory,/*hold_back_window=*/PacingController::kMinSleepTime): nullptr),
    
    • 如果 WebRTC-TaskQueuePacer 被启用,task_queue_pacer_ 将被初始化,表示使用 TaskQueue 驱动的实现。
    • 如果未启用,则使用传统的 PacedSender,并传入线程 process_thread_ 用于驱动调度。
    (2) 任务队列初始化

    任务队列 task_queue_ 的创建逻辑:

    task_queue_(task_queue_factory->CreateTaskQueue("rtp_send_controller",TaskQueueFactory::Priority::NORMAL))
    
    • rtp_send_controller 创建了一个中等优先级的任务队列。这意味着发送侧 RTP 控制器的任务拥有一定优先,但不会抢占核心实时任务(如音频编码)。
    (3) 启动策略

    根据 WebRTC-LazyPacerStart 配置决定是否延迟启动 Pacer:

    if (absl::StartsWith(trials->Lookup("WebRTC-LazyPacerStart"), "Disabled")) {EnsureStarted();
    }
    
    • “Lazy Start” 功能通常用于优化资源启动时的开销。如果禁用延迟启动,则直接调用 EnsureStarted() 启动所有功能。
    (4) Pacer 初始化

    为 Pacer 设置初始的码率:

    pacer()->SetPacingRates(DataRate::BitsPerSec(bitrate_config.start_bitrate_bps), DataRate::Zero());
    
    • SetPacingRates 需要传入目标的比特率(start_bitrate_bps)和填充数据的比特率(这里为 0)。

3.2、PacedSender:

PacedSender 是 WebRTC 中最核心的 Pacer 调度类,负责实现基于速率的节奏化数据发送。

PacedSender::PacedSender(Clock* clock,PacketRouter* packet_router,RtcEventLog* event_log,const WebRtcKeyValueConfig* field_trials,ProcessThread* process_thread): process_mode_( (field_trials != nullptr &&absl::StartsWith(field_trials->Lookup("WebRTC-Pacer-DynamicProcess"), "Enabled"))? PacingController::ProcessMode::kDynamic: PacingController::ProcessMode::kPeriodic),pacing_controller_(clock, // 构造 PacingControllerpacket_router,event_log,field_trials,process_mode_),clock_(clock),process_thread_(process_thread) {if (process_thread_)process_thread_->RegisterModule(&module_proxy_, RTC_FROM_HERE);
}

PacedSender 主要干两件事:

  • 设置PacedSender 处理模式为周期模式ProcessMode::kPeriodic (field_trials带回来的);
  • 创建了一个PacingController对象到pacing_controller_ ,Pacer模块中的主要逻辑都是由PacingController完成的;

构建好PacedSenderPacingCOntroller对象之后,最后启动Pacer线程,以后所有需要发送的数据包,都需要通过PacingControllerProcessPackets去发送。

3.3、两个重要函数:

1)PacingController::NextSendTime():

Pacing模块当中,获取每次执行的时间(5ms)

Timestamp PacingController::NextSendTime() const {// 。。。// kPeriodic模式(其实目前也仅仅支持这种周期模式)if (mode_ == ProcessMode::kPeriodic) {// In periodic non-probing mode, we just have a fixed interval.// 在周期性非探测模式下,我们只有一个固定间隔。就是使用上次处理的时间,加上min_packet_limit_(默认是5ms)return last_process_time_ + min_packet_limit_;}// ...return last_process_time_ + kPausedProcessInterval;
}

2)PacingController::ProcessPackets():

周期发送数据包。这个函数同样很长,我只保留关键逻辑:

  • 关键逻辑:
void PacingController::ProcessPackets() {// 动态模式目前版本不会用到(现在只用到周期模式)if (mode_ == ProcessMode::kDynamic) {// 。。。}// 判断当前是否应该发送保活包(当没有发送音视频数据的是时候,应该发送保活)if (ShouldSendKeepalive(now)) {// 。。。}// 如果处于暂停状态(重新进行媒体协商的时候,需要置为暂停状态),不能发送音视频数据包if (paused_) {return;}// 如果逝去的时间大于0(说明已经过了一段时间了),为media budget设置目标码率// webrtc是通过media budget设置目标码率的,ProcessPackets 正是根据media budget控制码流大小的// 如果发现media budget是500kbps,那么每次处理就是按照500kbps进行发送if (elapsed_time > TimeDelta::Zero()) {// 将前面设置给pacer的目标码率设置给media_budget}// 是否需要探测带宽码率,这块主要根据拥塞控制来if (is_probing) {// 获得pacing_info}// The paused state is checked in the loop since it leaves the critical// section allowing the paused state to be changed from other code.// 核心逻辑while (!paused_) { // 是否处于暂停状态// 下面单独分析}if (is_probing) {// 发送探测包}
}
  • 核心逻辑:(同样因为代码很多,只保留关键逻辑)
  // 核心逻辑while (!paused_) { // 是否处于暂停状态// Fetch the next packet, so long as queue is not empty or budget is not// exhausted.// 从Packet队列( RoundRobinPacketQueue packet_queue_ )中,取出我们要发送的packet// 如果我们获取到有数据的packet,那么就发送出去,但是如果我们没有获取到有数据的packet,rtp_packet为null,又分为两种情况:// 1.packet队列的确没有音视频数据包,这个时候,我们应该发送padding,让底层网络给我们将带宽留着//   否则,底层网络会将带宽进行回收,等到真正需要发送数据的时候,没有带宽,会造成延迟;// 2.有数据,但是我们现在已经发送的数据,达到了我们设定的目标码流,也不能让发送了。std::unique_ptr<RtpPacketToSend> rtp_packet =GetPendingPacket(pacing_info, target_send_time, now);if (rtp_packet == nullptr) {// 没有获取到数据包// 1、检查是否应该发送padding包,如果需要,将Padding包插入队列,并重新执行while循环。// 2、如果不需要,则退出while循环,说明这次不能再发送数据了。DataSize padding_to_add = PaddingToAdd(recommended_probe_size, data_sent);if (padding_to_add > DataSize::Zero()) {std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets =packet_sender_->GeneratePadding(padding_to_add);if (padding_packets.empty()) {// No padding packets were generated, quite send loop.break;}for (auto& packet : padding_packets) {EnqueuePacket(std::move(packet));}// Continue loop to send the padding that was just added.continue;}// Can't fetch new packet and no padding to send, exit send loop.break;}// 否则,说明我们获取了一个packet,那么计算packet的payload 大小是多少字节const RtpPacketMediaType packet_type = *rtp_packet->packet_type();DataSize packet_size = DataSize::Bytes(rtp_packet->payload_size() +rtp_packet->padding_size());// 将Packet发送出去packet_sender_->SendPacket(std::move(rtp_packet), pacing_info);for (auto& packet : packet_sender_->FetchFec()) {EnqueuePacket(std::move(packet));}data_sent += packet_size;// Send done, update send/process time to the target send time.// 记录发送的packet大小和时间(下次的发送时间就是根据我们这次更新的时间计算出来的)OnPacketSent(packet_type, packet_size, target_send_time);}

核心逻辑就是发数据包,有媒体数据就考虑发送媒体数据,没有就发送填充数据,进行保活,当然,发送两者的时候都应该考虑目标码率,已经超过我们设置的目标码率就等等再发。

  • 获取待发送的数据包:

    看看上面获取数据包的函数GetPendingPacket究竟干了啥:

    std::unique_ptr<RtpPacketToSend> PacingController::GetPendingPacket(const PacedPacketInfo& pacing_info,Timestamp target_send_time,Timestamp now) {if (packet_queue_.Empty()) {return nullptr;}// First, check if there is any reason _not_ to send the next queued packet.// Unpaced audio packets and probes are exempted from send checks.// 不需要平滑处理的特殊情况:// pace_audio_ 为false,说明音频包不需要平滑处理,并且,// packet_queue_.LeadingAudioPacketEnqueueTime().has_value() 说明队列中下一个数据包是音频包bool unpaced_audio_packet =!pace_audio_ && packet_queue_.LeadingAudioPacketEnqueueTime().has_value();bool is_probe = pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe;if (!unpaced_audio_packet && !is_probe) {// 网络拥塞状况下不能发送if (Congested()) {// Don't send anything if congested.return nullptr;}// 没有拥塞,会检测模式是否为周期模式if (mode_ == ProcessMode::kPeriodic) {// media_budget_ 中可供我们使用的字节数不大于0,表示我们已经达到了目标码率,我们也不发送if (media_budget_.bytes_remaining() <= 0) {// Not enough budget.return nullptr;}} else {// 动态模式现在还不成熟,不关心}}// 如果不是上面的情况,那么,我们需要从队列中pop出一个packet,让ProcessPackets函数将其发送出去return packet_queue_.Pop();
    }

    主要就是先做了一些发送状态的校验:网络拥塞情况下不能发送、达到目标码率了也不能发送,如果校验通过可以发送,就从队列中取出一个数据包进行发送。

四、总结:

本文主要介绍了Pacer模块的作用,以及相关重要的框架代码,其实还有很多细节后面再打开看看。

相关文章:

WebRTC服务质量(09)- Pacer机制(01) 流程概述

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…...

MIGRATE_ISOLATE浅析

在linux内核的migratetype中&#xff0c;有MIGRATE_ISOLATE这样一个内存迁移类型&#xff0c;注释里写着can’t allocate from here&#xff0c;这个是怎么做到的呢&#xff1f;他又有什么作用呢&#xff1f; 本文分析基于linux4.19.195 可以看到内核里&#xff0c;是函数set_…...

[bug]java导出csv用Microsoft Office Excel打开乱码解决

[bug]java导出csv用Microsoft Office Excel打开乱码 ‍ 现象 首先这个csv文件用macbook自带的 "Numbers表格" 软件打开是不乱码的, 但是使用者是Windows系统,他的电脑没有"Numbers表格"工具, ​​ 他用Microsoft Office Excel打开之后出现乱码,如下图…...

Ftrans数据摆渡系统 搭建安全便捷跨网文件传输通道

一、专业数据摆渡系统对企业的意义 专业的数据摆渡系统对企业具有重要意义&#xff0c;主要体现在以下几个方面‌&#xff1a; 1、‌数据安全性‌&#xff1a;数据摆渡系统通过加密传输、访问控制和审计日志等功能&#xff0c;确保数据在传输和存储过程中的安全性。 2、‌高…...

LabVIEW条件配置对话框

条件配置对话框&#xff08;Configure Condition Dialog Box&#xff09; 要求&#xff1a;Base Development System 当右键单击**条件禁用结构&#xff08;Conditional Disable Structure&#xff09;**并选择以下选项时&#xff0c;会显示此对话框&#xff1a; Add Subdiagr…...

【MySQL学习笔记】关于索引

文章目录 【MySQL学习笔记】关于索引1.索引数据结构2.索引存储3.联合索引3.1 联合索引的b树结构3.2 索引覆盖&#xff1f;回表&#xff1f;3.3 联合索引最左匹配原则3.5 索引下推 4.索引失效 【MySQL学习笔记】关于索引 1.索引数据结构 索引是一种能提高查询速度的数据结构。…...

面试经典 150 题——数组/字符串(一)

文章目录 1、合并两个有序数组1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2、移除元素2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、删除有序数组中的重复项3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 4、删除有序数组中的重复项 II4.1 题目链接4.2 题…...

Ingress-Nginx Annotations 指南:配置要点全方面解读(下)

文章目录 1.HTTP2 Push Preload2.Server Alias3.Server snippet4.Client Body Buffer Size5.External Authentication6.Global External Authentication7.Rate Limiting8.Global Rate Limiting9.Permanent Redirect10.Permanent Redirect Code11.Temporal Redirect12.SSL Passt…...

Ramfs, rootfs 和 initramfs

什么是ramfs Ramfs 是一个非常简单的文件系统&#xff0c;它将 Linux 的磁盘缓存机制&#xff08;页面缓存和 dentry 缓存&#xff09;导出为可动态调整大小的基于 RAM 的文件系统。 通常&#xff0c;Linux 会将所有文件缓存在内存中。从后备存储&#xff08;通常是文件系统所…...

Xdebug

1、开启xdebug扩展 2、修改一下php.ini文件 xdebug.remote_enable 1 xdebug.remote_autostart 13、vscode安装插件php debug 4、生成launch.json文件&#xff0c;好像啥都不用改 5、vscode没有配置php路径的&#xff0c;需要去配置&#xff1a; 6、发起请求 8、代码断…...

LinkedList类 (链表)

目录 一. LinkedList 基本介绍 二. LinkedList 中的法及其应用 1. 添加元素 (1) add() (2) addAll() (3) addFirst() (4) addLast() 2. 删除元素 (1) remove() (2) removeAll() (3) removeFirst() (4) removeLast() 3. 遍历元素 (1) for 循环遍历 (2) for - each …...

删除拼排序链表中的重复元素(最优解)

题目来源 82. 删除排序链表中的重复元素 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head…...

arm架构 uos操作系统离线安装k8s

目录 操作系统信息 安装文件准备 主机准备 主机配置 配置hosts&#xff08;所有节点&#xff09; 关闭防火墙、selinux、swap、dnsmasq(所有节点) 系统参数设置(所有节点) 配置ipvs功能(所有节点) 安装docker&#xff08;所有节点&#xff09; 卸载老版本 安装docke…...

影视仓最新接口+内置本包方法的研究(2024.12.27)

近日喜欢上了研究影视的本地仓库内置&#xff0c;也做了一个分享到了群里。 内置本地仓库包的好处很明显&#xff0c;当前线路接口都是依赖网络上的代码站存放&#xff0c;如果维护者删除那就GG。 虽然有高手制作了很多本地包&#xff0c;但推送本地包到APP&#xff0c;难倒一片…...

Unity开发AR之Vuforia-MultiTarget笔记

前言 在增强现实(AR)技术蓬勃发展的今天,越来越多的开发者开始探索如何将AR应用于各种场景中。Vuforia作为一个领先的AR开发平台,为开发者提供了强大的工具和功能,使得创建AR体验变得更加简单和直观。本文将为您介绍Vuforia的基本概念、特点,以及如何配置和使用MultiTar…...

软体机器人研究报告:设计方法、材料与驱动、感知与控制

软体机器人因其出色的可变形性和高适应性受到了广泛关注&#xff0c;这些特性使其在医疗、救援、探测等复杂场景中展现出独特的优势和巨大的应用潜力。研究人员对软体机器人的设计方法、材料与驱动技术、感知与控制策略等方面进行深入研究&#xff0c;取得了一系列成果。 本文汇…...

XL系列433芯片、2.4G收发芯片 通讯对码说明

XL系列433芯片对码说明&#xff1a; 发射芯片 XL4456 通过数据脚接收高低电平然后经过调制将波形发出&#xff0c;而接收芯片 XL520 通过接收波形后进行解调&#xff0c;数据脚输出高低电平。至于具体的通信协议&#xff0c;需要用户自定义&#xff0c;一般而言&#xff0c;使…...

Redis的持久化机制

目录 RDB 触发机制 bgsave命令执行流程 RDB的文件处理 RDB的优缺点 AOF AOF工作流程 AOF缓冲区同步文件策略 AOF重写机制 AOF重写触发机制 AOF重写流程 在这里我们知道&#xff0c;redis存储的数据是存储在缓存中的&#xff0c;重启服务器数据就不存在了。要想持久化…...

LeetCode 83 :删除排链表中的重复元素

题目&#xff1a; 地址&#xff1a;https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ 方法一&#xff1a; 方法二&#xff1a; package com.zy.leetcode.LeetCode_04;/*** Author: zy* Date: 2024-12-25-15:19* Description: 删除排链表中的里复元素* …...

复习打卡大数据篇——Hadoop MapReduce

目录 1. MapReduce基本介绍 2. MapReduce原理 1. MapReduce基本介绍 什么是MapReduce MapReduce是一个分布式运算程序的编程框架&#xff0c;核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在Hadoop集群上。 MapRed…...

无法验证服务器身份是什么意思?

当你尝试访问某个网站或连接到服务器时&#xff0c;系统突然弹出一个提示&#xff0c;告诉你“无法验证服务器身份”?这到底是什么意思?在如今这个网络安全日益重要的时代&#xff0c;了解这种提示的含义以及背后的原因是非常必要的。今天&#xff0c;我们就来了解一下“无法…...

用友-友数聚科技CPAS审计管理系统V4 getCurserIfAllowLogin存在SQL注入漏洞

免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...

Java 深拷贝全面解析

1. 引言 在 Java 编程中&#xff0c;对象之间的复制是一个常见的需求。根据复制的深度不同&#xff0c;我们可以将复制分为浅拷贝和深拷贝。本文将深入探讨 深拷贝&#xff08;Deep Copy&#xff09; 的概念、应用场景、具体实现方法及其优缺点&#xff0c;并提供一些实用的建…...

极狐GitLab 17.7正式发布,可从 GitLab 丝滑迁移至极狐GitLab【一】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…...

云原生架构中的中间件容器化:优劣势与实践探索

在云原生架构逐步推进的过程中&#xff0c;许多企业已经开始将应用和服务容器化&#xff0c;以充分利用云计算带来的弹性和自动化。随着容器技术的发展&#xff0c;容器化不仅仅限于应用层&#xff0c;越来越多的中间件也被考虑纳入容器化范畴&#xff0c;包括Redis、Kafka、Ra…...

Go+chromedp实现Web UI自动化测试

1.为什么使用go进行UI自动化测试&#xff1f; 速度&#xff1a;Go速度很快&#xff0c;这在运行包含数百个UI测试的测试套件时是一个巨大的优势 并发性&#xff1a;可以利用Go的内置并发性(goroutines)来并行化测试执行 简单&#xff1a;Go的简约语法允许您编写可读且可维护…...

Adversarial Machine Learning(对抗机器学习)

之前把机器学习&#xff08;Machine Learning&#xff09;的安全问题简单记录了一下&#xff0c;这里有深入研究了一些具体的概念&#xff0c;这里记录一下方便以后查阅。 Adversarial Machine Learning&#xff08;对抗机器学习&#xff09; Adversarial Examples 相关内容Eva…...

EleutherAI/pythia-70m

EleutherAI/pythia-70m” 是由 EleutherAI 开发的一个小型开源语言模型&#xff0c;它是 Pythia Scaling Suite 系列中参数量最小的模型&#xff0c;拥有大约 7000 万个参数。这个模型主要旨在促进对语言模型可解释性的研究&#xff1b; Pythia Scaling Suite是为促进可解释性…...

【C#】C#打印当前时间以及TimeSpan()介绍

1. C#打印当前时间 string currentDate DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");Console.WriteLine(currentDate);2. TimeSpan()介绍 TimeSpan(long ticks)的单位是100ns //500ms new TimeSpan(10*1000*500);参考&#xff1a; C#-TimeSpan-计算时间差...

典型常见的基于知识蒸馏的目标检测方法总结二

来源&#xff1a;https://github.com/LutingWang/awesome-knowledge-distillation-for-object-detection收录的方法 NeurIPS 2017&#xff1a;Learning Efficient Object Detection Models with Knowledge Distillation CVPR 2017&#xff1a;Mimicking Very Efficient Networ…...

设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)

前言&#xff1a; 设计一个完整的 监控摄像头物联网 IoT 平台 涉及 视频直播和点播、WebRTC 和 文件存储模块&#xff0c;可以分为以下几个主要部分&#xff1a;摄像头设备、服务端处理、Web 前端、视频流存储和回放。以下是结合这些技术的一个具体完整流程设计&#xff0c;涵盖…...

C# OpenCV机器视觉:凸包检测

在一个看似平常却又暗藏玄机的午后&#xff0c;阿强正悠闲地坐在实验室里&#xff0c;翘着二郎腿&#xff0c;哼着小曲儿&#xff0c;美滋滋地品尝着手中那杯热气腾腾的咖啡&#xff0c;仿佛整个世界都与他无关。突然&#xff0c;实验室的门 “砰” 的一声被撞开&#xff0c;小…...

yii2 手动添加 phpoffice\phpexcel

1.下载地址&#xff1a;https://github.com/PHPOffice/PHPExcel 2.解压并修改文件名为phpexcel 在yii项目的vendor目录下创建一个文件夹命名为phpoffice 把phpexcel目录放到phpoffic文件夹下 查看vendor\phpoffice\phpexcel目录下会看到这些文件 3.到vendor\composer目录下…...

Apifox 12月更新|接口的测试覆盖情况、测试场景支持修改记录、迭代分支能力升级、自定义项目角色权限、接口可评论

Apifox 新版本上线啦&#xff01;&#xff01;&#xff01; 在快速迭代的开发流程中&#xff0c;接口测试工具的强大功能往往决定了项目的效率和质量。而 Apifox 在 12 月的更新中&#xff0c;再次引领潮流&#xff0c;推出了一系列重磅功能&#xff01;测试覆盖情况分析、场景…...

“库存管理软件的用户体验”:界面与交互设计

3.1可行性分析 开发者在进行开发系统之前&#xff0c;都需要进行可行性分析&#xff0c;保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该库存管理软件所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识&#xff0c;同…...

Mysql大数据量表分页查询性能优化

一、模拟场景 1、产品表t_product,数据量500万+ 2、未做任何优化前,cout查询时间大约4秒;LIMIT offset, count 时,offset 值较大时查询时间越久。 count查询 SELECT COUNT(*) AS total FROM t_product WHERE deleted = 0 AND tenant_id = 1 分页查询 SELECT * FROM t_…...

Linux基础--1.1 什么是 Linux 操作系统

Linux 的起源与定义 Linux 是一种开源的操作系统&#xff0c;由 Linus Torvalds 于 1991 年首次发布。它基于 UNIX 操作系统&#xff0c;并以自由和开放为核心理念。Linux 的代码可以由任何人查看、修改并发布&#xff0c;这是它与许多专有操作系统&#xff08;如 Windows 和 …...

数电实验期末作业——基于FPGA的数字时钟设计

1. 概述 本系统主要完成数字电子钟的以下功能&#xff1a; 1.计时功能&#xff08;24小时&#xff09; 2.闹钟功能&#xff08;设置闹钟以及到时播放音乐&#xff09; 3.校时功能 4.其他简单功能&#xff08;清零、输入频率选择&#xff08;1hz、500hz、5khz&#xff09;、…...

hdfs命令(三)- hdfs 管理命令(三)- hdfs dfsadmin命令

文章目录 前言一、hdfs分布式文件系统管理命令1. 介绍2. 语法及解释3. 命令3.1 生成HDFS集群的状态报告3.1.1 语法及解释3.1.2 示例 3.2 重新加载配置文件并更新NameNode中的节点列表3.3 刷新指定DataNode上的NameNode信息3.3.1 语法 3.4 获取并显示指定DataNode的信息3.4.1 语…...

TCP off-path exploits(又一个弄巧成拙的例子)

承接前面几篇文章的观点&#xff0c;本文用一个安全攻击的例子说明为了解决一个伤害很低的低概率问题&#xff0c;会引入多么大的麻烦&#xff0c;这次是可怕的被攻击 (⊙o⊙)。 TCP 端口号只有 16bit&#xff0c;序列号只有 32bit&#xff0c;这意味着在强大攻击算力面前&…...

Docker【初识Docker】

目录 为什么会出现Docker这门技术喃&#xff1f; 应用开发和部署的困境 容器技术的先兆 Docker 的出现&#xff1a;简化容器化 Docker 技术的关键创新&#xff1a; Docker 的广泛应用和变革 什么是 Docker&#xff1f; Docker的历史 早期背景&#xff1a;容器化和虚拟化…...

开机存活脚本

vim datastadard_alive.sh #!/bin/bashPORT18086 # 替换为你想要检查的端口号 dt$(date %Y-%m-%d)# 使用netstat检查端口是否存在 if netstat -tuln | grep -q ":$PORT"; thenecho "$dt Port $PORT is in use" > /opt/datastadard/logs/alive.log# 如…...

【elementplus】中文模式

设置中文 <el-date-picker v-model“userAddKey” type“daterange” style“width: 240px” start-placeholder“Start Date” end-placeholder“End Date” change“handleUserAddChange” /> 引入&#xff1a; import zhCn from “element-plus/es/locale/lang/zh-cn”…...

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好&#xff0c;今天我们来聊聊Docker容器管理中的一个非常有用的命令&#xff1a;docker exec。在日常工作中&#xff0c;我们经常需要在运行中的Docker容器内执行各种命令&#xff0c;docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子&#xff0c;…...

FPGA的DMA应用——pcileech

硬件通过pcie总线&#xff0c;访存本机的内存&#xff0c;并进行修改&#xff0c;可以进行很多操作。 学习视频&#xff1a;乱讲DMA及TLP 1-pcileech项目简介和自定义模块介绍_哔哩哔哩_bilibili vivado2024.1的下载文章链接和地址&#xff1a;AMD-Xilinx Vivado™ 2024.1 现…...

前后端数据交互

一、后端部分 1.创建Spring Boot项目&#xff1a;在IDEA中创建一个Spring Boot项目&#xff0c;引入必要的依赖。 2.编写Controller层&#xff1a;在Spring Boot项目中创建Controller&#xff0c;用于处理前端的请求和响应数据。 RestController RequestMapping("/demo/s…...

将现有Web 网页封装为macOS应用

文章目录 方式一&#xff1a;Unite for macOS方式二&#xff1a;Web2Desk方式三&#xff1a;Nativefier方式四&#xff1a;Flutter Flutter WebView Plugin总结 方式一&#xff1a;Unite for macOS Unite 是一款专为 macOS 设计的工具&#xff0c;可以将任意 Web 页面快速封装…...

代码随想录Day52 101. 孤岛的总面积,102. 沉没孤岛,103. 水流问题,104.建造最大岛屿。

1.孤岛的总面积 卡码网&#xff1a;101. 孤岛的总面积(opens new window) 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域&#xff0c;且完全被水域单元格…...

Python毕业设计选题:基于Python的社区爱心养老管理系统设计与实现_django

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 身体健康界面 公共书籍界面 借阅信息界面 归还…...

逆袭之路(11)——python网络爬虫:原理、应用、风险与应对策略

困厄铸剑心&#xff0c;逆袭展锋芒。 寒苦凝壮志&#xff0c;腾跃绘华章。 我要逆袭。 目录 一、引言 二、网络爬虫的基本原理 &#xff08;一&#xff09;网络请求与响应 &#xff08;二&#xff09;网页解析 &#xff08;三&#xff09;爬行策略 三、网络爬虫的应用领…...