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

openssl中BIO的使用

BIO是OpenSSL的一个重要的结构和概念,是对数据IO与传递处理的一种类型抽象和功能封装,这里所说的数据IO与传递的“介质”包括:内存、文件、日志、标准设备、网络socket等,“处理”包括简单、加/解密、摘要、ssl协议下的读/写等的数据变换。

本文主要介绍了BIO的结构和使用方法,并以示例方式给出了一种对BIO的封装,可为下一步与socket的相关操作结合,编写自定义的“加密/解密流”。

本文示例适用于openssl3.0+。

1.概念

BIO是针对数据传递而设计的逻辑结构,因此它基本的概念模型是“管道”:数据由BIO一端进入,另一端流出,中间也可能进行数据变换。这样的“管道”结构可以依据是否有“缓存”,出入口等条件进行划分。

OpenSSL中将BIO分为两种类型:

  • Filter BIO:就是纯管道型BIO,数据不能保存在其中。
  • source/sink BIO:自带有容器的BIO,数据进行缓存,如果进一步细分,source BIO就是只出不进BIO,sink BIO就是只进不出BIO。

两种类型的BIO的概念示意图如上图所示。可以想象,如果将BIO首尾连接起来,就会构成BIO链,也如上图所示。BIO链在使用上,虽然仅对首尾BIO进行了读写操作,但是这种操作是会依次传递给下一个BIO的,因而BIO链逻辑上看作是一个复杂的BIO。

2.类型

OpenSSL中已经预定义了若干种BIO,直接可以使用它们。

主要Source/Sink类型BIO

  •  BIO_s_file/ BIO_s_fd:文件BIO,BIO_s_file对应FILE*,而BIO_s_fd对应POSIX文件描述符,它们可用于写入和读取文件。
  • BIO_s_socket:网络socketBIO,用于通过网络进行通信。
  • BIO_s_null: 空BIO,类似/dev/null,只能写入,读取数据会导致EOF。
  • BIO_s_mem:内存BIO,用于写入和读取内存。
  • BIO_s_bio:一种特别的BIO,被称为BIO pair,后文单独说明。

主要Filter类型BIO

  • BIO_f_base64:base64 BIO,通过此BIO的BIO_write将数据编码为base64格式, BIO_read通过此BIO解码base64格式的数据。
  • BIO_f_cipher:密码BIO,通过它的数据会被加/解密,密码算法可以设置。
  • BIO_f_md:摘要计算BIO,它不会修改通过它的数据,而仅计算流经其中的数据摘要,摘要算法可以设置,使用特殊功能检索计算出的摘要。
  • BIO_f_buffer:缓冲BIO,它也不会更改通过它的数据。写入此BIO的数据被缓冲,因此并非每次对该BIO的写入操作都会导致将数据写入下一个BIO。至于阅读,情况类似。这样可以减少位于缓冲IO后面的BIO上的IO操作数。
  • BIO_f_ssl :SSL/TLS 协议BIO,通过它的数据会按照协议规则进行加解密
  • 3.基本使用函数

创建/释放函数为:

BIO *BIO_new(const BIO_METHOD *)
BIO_free_all(BIO *)

设置/控制基本函数为:

BIO_ctrl(BIO *,int,long ,void *)

以此函数为基础,定义了一些方便使用的宏:BIO_reset,BIO_tell,BIO_eof,BIO_flush等
读写操作的基本函数为:

int BIO_read_ex(BIO *, void *, size_t, size_t *)
int BIO_write_ex(BIO *, const void *, size_t, size_t *)

对于BIO链,bio_st结构中有变量next_bio,prev_bio,可以指向其前后的BIO,这也是BIO链式操作的基础。BIO链的基本操作函数为:

BIO * BIO_push(BIO *a,BIO *b);
BIO * BIO_pop(BIO *b);

前者将b链接到a之后,返回b,后者将b从链条上摘除,返回b,原来的链条依然完整。

BIO还有一些辅助函数,例如处理错误,获取状态等函数。

4.BIO Pair

BIO对是一种比较特别的BIO,它由两个BIO组成,但从它的实现代码来看,它似乎是与BIO平行的一种实现方式,因而不能单纯的用BIO链来说明,它的逻辑结构如下图所示。

BIO pair连接两个外部端A,B,从外部来看,A端写,则可从B端读出;B端写,则可从A端读出。从内部来看,有两个内存型BIOA和BIOB,分别与A端和B端相连,它们有各自的缓存,A端存入和B端读取的数据,利用的是BIOA缓存,B端写入A端读取则利用的是BIOB的缓存。

因此BIO pair类似于“双向有缓存管道”,从任一端写入,另一端读出,由于内存缓存的利用,使得一端的读/写操作都是“即刻”完成的,它不用关心另一端什么时候做写/读操作,这就是典型的异步操作。目前很多网络通信库采用的都是异步读写,因而BIO pair这种应用模型是OpenSSL适配这些网络库的一个重要方法。

创建BIO pair的简洁方法是BIO_new_bio_pair,它实际上是 BIO_new, BIO_make_bio_pair,  BIO_set_write_buf_size的组合。

5.构造自定义BIO类型

OpenSSL已定义了若干BIO,当然也可以自定义一个。下面的示例构造了一个简单的CMYBIO,以此来说明BIO的工作原理。

class CMYBIO
{
private:static int write_ex(BIO* h, const char* buf, size_t num, size_t * len){printf("CMYBIO::write_ex\n");for (int i = 0; i < num; ++i)  printf("%c", buf[i]);printf("\n");*len = num;return 1;}static int read_ex(BIO* h, char* buf, size_t size, size_t* len){printf("CMYBIO::read_ex\n");unsigned int* opt = (unsigned int*)BIO_get_data(h);if (*opt == 0){size = size > 6 ? 6 : size;memcpy(buf, "openss", size);*len = size;
//			BIO_clear_retry_flags(h);
//			BIO_copy_next_retry(h);return 1;}if (*opt == 1){size = 9;memcpy(buf, "MTIzNDU2\n", size);           //base64("123456")*len = size;BIO_clear_retry_flags(h);
//			BIO_copy_next_retry(h);return 1;}return 0;}static long ctrl(BIO* h, int cmd, long arg1, void* arg2){printf("CMYBIO::ctrl[%d]\n", cmd);if (cmd == 0xff){unsigned int* opt = (unsigned int*)BIO_get_data(h);*opt = arg1;}return 1;}static int create(BIO* bio){printf("CMYBIO::create\n");BIO_set_init(bio, 1);            //”init” must be set explicitly,otherwise “read”/”write” methods will be invoked. Although it seems odd, the “framework” would not do It for you by the returned value. unsigned int* opt =(unsigned int*) malloc(sizeof(int));*opt = 0;BIO_set_data(bio,opt);return 1;}static int destory(BIO* bio){printf("CMYBIO::destory\n");unsigned int* opt=(unsigned int*)BIO_get_data(bio);free(opt);return 1;}static BIO_METHOD* method;
public:static BIO_METHOD* BIO_s_my(){return CMYBIO::method;}static void UnInit(){BIO_meth_free(CMYBIO::method);}static void Init(void){CMYBIO::method = BIO_meth_new((100 | BIO_TYPE_SOURCE_SINK), "My BIO");int r;r = BIO_meth_set_create(CMYBIO::method, CMYBIO::create);r = BIO_meth_set_destroy(CMYBIO::method, CMYBIO::destory);r = BIO_meth_set_write_ex(CMYBIO::method,  CMYBIO::write_ex);r=BIO_meth_set_read_ex(CMYBIO::method, CMYBIO::read_ex);r=BIO_meth_set_puts(CMYBIO::method,  nullptr);r=BIO_meth_set_gets(CMYBIO::method, nullptr);        r=BIO_meth_set_ctrl(CMYBIO::method, CMYBIO::ctrl);r=BIO_meth_set_callback_ctrl(CMYBIO::method, nullptr);}};BIO_METHOD* CMYBIO::method=nullptr;

下面的代码使用了上面构造的CMYBIO,其中第一段是单独使用CMYBIO,第二段是与BIO_f_base64组成链式应用。CMYBIO作为单独应用,构造的功能已经够用,但组成链式应用,由于链式调用需要在每个具体的实现方法内来完成,因此上面的代码还不够,为简化,这里仅把CMYBIO作为链式应用的最后一级来使用。

long bio_cb(BIO* b, int oper, const char* argp, size_t len, int argi, long argl, int ret, size_t* processed)
{printf("bio callback:%d, %u\n", oper,(unsigned int)len);return 1;
}
void test_bio()
{BIO* bmy = NULL;size_t s = 0;int len = 0;char* out = NULL;char cc[24];memset(cc, 0, sizeof(cc));CMYBIO::Init();bmy = BIO_new(CMYBIO::BIO_s_my());BIO_set_callback_ex(bmy, bio_cb);len = BIO_write_ex(bmy, "openssl", 7, &s);printf("BIO_write_ex return [%d, %u]\n\n", len, (unsigned int)s);len = 7;out = (char*)OPENSSL_malloc(len);memset(out, 0, len);len = BIO_read_ex(bmy, out, len-1, &s);printf("BIO_read_ex return [%d,%u]%s\n", len, (unsigned int)s, out);OPENSSL_free(out);BIO_free(bmy);printf("--------------------------------\n");BIO* b64 = BIO_new(BIO_f_base64());BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);bmy = BIO_new(CMYBIO::BIO_s_my());BIO_push(b64, bmy);len=BIO_write_ex(b64, "123456", 6, &s);printf("BIO_write_ex return [%d, %u]\n\n", len, (unsigned int)s);BIO_flush(b64);             //important!!!BIO_ctrl(bmy, 0xff, 1, nullptr);len = BIO_read_ex(b64, cc, sizeof(cc)- 1, &s);printf("BIO_read_ex return [%d,%u]%s\n\n", len, (unsigned int)s, cc);//OPENSSL_free(out);BIO_free_all(b64);CMYBIO::UnInit();
}

整个过程输出如下图所示。前一个示例主要展示CMYBIO中各方法的调用过程,其中还设置了“钩子”函数,从输出可以清晰看出BIO的工作过程。后一个示例稍有些麻烦,其中增加了CMYBIO内部的设置,从而可以实现不同的效果。

需要注意的是,BIO_f_base64有其特殊之处,对于“write”,需要在完成后调用flush才能正确工作,对于“read”,编码串结束的标志是“\n”,但还是要设置BIO_set_flags(b, BIO_FLAGS_BASE64_NO_NL),否则可能会有错误。

相关文章:

openssl中BIO的使用

BIO是OpenSSL的一个重要的结构和概念&#xff0c;是对数据IO与传递处理的一种类型抽象和功能封装&#xff0c;这里所说的数据IO与传递的“介质”包括&#xff1a;内存、文件、日志、标准设备、网络socket等&#xff0c;“处理”包括简单、加/解密、摘要、ssl协议下的读/写等的数…...

电动汽车充电设施可调能力聚合评估与预测

电动汽车充电设施可调能力聚合评估与预测 项目概述 本项目基于论文《大规模电动汽车充换电设施可调能力聚合评估与预测》(鲍志远&#xff0c;胡泽春)&#xff0c;实现了电动汽车充电设施可调能力的聚合评估与预测方法。 主要文件 real_data_model.m: 使用真实数据实现LSTM线…...

Git clone时出现SSL certificate problem unable to get local issuer certificate

正确解决方法 git config --global http.sslVerify false错误解决方法&#xff1a;&#xff08;主要是看错了嘿嘿&#xff0c;但是如果是 OpenSSL SSL_read: Connection was reset, errno 10054 Failed to connect to github.com port 443: Timed out 原…...

requests库

模拟请求获取网页源代码 如下 import requestsr requests.get(https://spa1.scrape.center/page/1) print(r.text) 源码如下 GET请求 示例网站为 https://httpbin.org import requests r requests.get(https://httpbin.org/) print(r.text) 所显示的结果如下 {"a…...

基于springboot的海洋环保知识分享系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…...

安科瑞ADL3000-E-A/KC三相交流电能表CE认证导轨表

1 概述 ADL3000-E-A 是一款为供电系统、工矿企业以及公用事业单位设计的智能电表&#xff0c;用于计算耗电量并管理用电需求。它具备高精度、体积小以及安装简便的特点。它将所有电气参数的测量与综合电能计量及管理功能集成在一起&#xff0c;可提供过去 12 个月的各类数据&a…...

红黑树算法笔记

文章目录 红黑树 (Red-Black Tree) 学习笔记0. 节点结构与哨兵节点1. 什么是红黑树&#xff1f;2. 红黑树的五个核心性质3. 为什么需要红黑树&#xff1f;4. 红黑树的基本操作a. 查找 (Search)b. 插入 (Insert)c. 删除 (Delete) 5. 维护平衡的关键操作a. 变色 (Recoloring)b. 旋…...

【Axios】解决Axios下载二进制文件返回空对象的问题

【Axios】解决Axios下载二进制文件返回空对象的问题 问题背景 在一个基于Vue 3的项目中,我们使用Axios下载Excel文件,但遇到了一个奇怪的问题:文件能成功下载下来,但打开时显示内容为[object Object]无法使用。 当我们执行下载代码: const response = await downloadT…...

2.MySQL数据库操作

一.MySQL数据库介绍 数据库目前标准指令集是SQL&#xff0c;即结构化查询语言。SQL语言主要由以下几部分组成 DDL&#xff08;数据定义语言&#xff09;&#xff1a;用来建立数据库、数据库对象和定义字段&#xff0c;如create、alter、drop。 DML&#xff08;数据操纵语言&…...

01.three官方示例+编辑器+AI快速学习webgl_animation_keyframes

实例&#xff1a;examples/webgl_animation_keyframes.html 在这里插入图片描述 重点关注&#xff1a; AnimationMixer&#xff1a;管理模型的所有动画AnimationClip&#xff1a;表示一个完整的动画ClipAction&#xff1a;控制动画的播放状态&#xff08;播放、暂停、速度等&am…...

在 Spring Boot 中实现动态线程池的全面指南

动态线程池是一种线程池管理方案&#xff0c;允许在运行时根据业务需求动态调整线程池参数&#xff08;如核心线程数、最大线程数、队列容量等&#xff09;&#xff0c;以优化资源利用率和系统性能。在 Spring Boot 中&#xff0c;动态线程池可以通过 Java 的 ThreadPoolExecut…...

餐饮行业新风口:上门厨师服务系统的技术实现路径

上门做饭正在成为下一个万亿级风口&#xff01;当外卖平台被预制菜攻陷&#xff0c;当年轻人对着料理包无可奈何&#xff0c;一个全新的餐饮模式正在悄然崛起。 我们的市场调研显示&#xff0c;83%的消费者无法分辨外卖是否使用预制菜&#xff0c;76%的年轻人愿意为透明烹饪过程…...

odoo-049 Pycharm 中 git stash 后有pyc 文件,如何删除pyc文件

文章目录 问题描述解决思路正确的去除 git 跟踪 pyc文件的做法 问题描述 查看本地 stash 列表 stash 后有很多 pyc 文件都被 git 追踪了&#xff0c;这样不合理&#xff0c;而且等 unstash 的时候就会有问题 解决思路 尝试方法&#xff1a; 递归地删除指定文件夹及其子目录中…...

线程同步机制

synchronized 实现线程同步的关键字&#xff0c;用来防止多个线程同时访问某个代码块或方法&#xff0c;避免并发冲突和数据不一致。通过持有一把唯一的对象锁&#xff0c;谁拿到了谁就能执行&#xff0c;谁没拿到只能等待锁释放。 1. 修饰实例方法&#xff08;锁当前实例&…...

YOLO目标检测算法

文章目录 前言一、目标检测算法简介1、传统目标检测算法&#xff08;1&#xff09;R-CNN算法简介&#xff08;2&#xff09;Fast R-CNN算法简介&#xff08;3&#xff09;Faster R-CNN算法简介 2、目标检测中的算法设计范式&#xff08;1&#xff09;one-stage&#xff08;2&am…...

【官方题解】StarryCoding 入门教育赛 2 | acm | 蓝桥杯 | 新手入门

比赛传送门&#xff1a; 本场比赛开始时题面存在一些问题&#xff0c;私密马赛&#xff01; A.池化【入门教育赛】 根据题目所给公式计算即可。 #include "bits/stdc.h"signed main() {int t; std::cin >> t;while (t --) {int l, k, s, p; std::cin >&…...

《让歌声跨越山海:Flutter借助Agora SDK实现高质量连麦合唱》

对于Flutter开发者而言&#xff0c;借助Agora SDK实现这一功能&#xff0c;不仅能为用户带来前所未有的社交体验&#xff0c;更是在激烈的市场竞争中脱颖而出的关键。 Agora SDK作为实时通信领域的佼佼者&#xff0c;拥有一系列令人瞩目的特性&#xff0c;使其成为实现高质量连…...

1.3.2 linux音频PulseAudio详细介绍

PulseAudio 是一个在 Linux 及其他类 Unix 操作系统中广泛使用的声音服务器&#xff08;Sound Server&#xff09;&#xff0c;它为不同的音频应用程序提供了一种中间层&#xff0c;以方便管理和控制音频流。下面将详细介绍 PulseAudio 的相关内容&#xff0c;包括其基本概念、…...

8.1.Kubernetes进阶

目录 一、Kubernetes核心原理深度解析 架构设计精髓 • 控制平面组件&#xff08;API Server、etcd、Controller Manager、Scheduler&#xff09;协作流程 • 数据平面&#xff08;kubelet、容器运行时、CNI/CSI插件&#xff09;核心工作机制 API对象与声明式模型 • CRD&…...

electron 结合 react(cra创建的) 创建桌面应用和打包桌面应用

我说一下 react 结合 electron 如果打包和使用&#xff0c;以及其中可能会遇到的问题&#xff0c;这里只做简单功能的演示 我们先通过 cra 创建一个 react 项目&#xff0c;然后安装相关依赖&#xff0c;之后启动 npx create-react-app react_electron cd react_electron np…...

C++23 views::chunk_by (P2443R1) 详解

文章目录 引言C23 范围库概述范围视图&#xff08;Range Views&#xff09;范围算法&#xff08;Range Algorithms&#xff09;范围适配器&#xff08;Range Adapters&#xff09; std::views::chunk_by 介绍基本概念特性使用场景 示例代码简单示例自定义谓词示例 总结 引言 在…...

MySQL核心内容【持续更新中】

MySQL核心内容 文章目录 MySQL核心内容1.MySQL核心内容目录2.MySQL知识面扩展3.MySQL安装4.MySQL配置目录介绍Mysql配置远程ip连接 5.MySQL基础1.MySQL数据类型1.数值类型2.字符串类型3.日期和时间类型4.enum和set 2.MySQL运算符1.算数运算符2.逻辑运算符3.比较运算符 3.MySQL完…...

【高级IO】多路转接之单线程Reactor

这里写目录标题 一.Epoll的两种工作模式二.单线程Reactor1.Connection模块2.Reactor服务器模块2.1初始化Init2.2启动循环服务器Loop2.3事件派发Dispatcher2.4连接管理器Accepter2.5事件管理器Receiver2.6发送管理器Sender 3.上层业务模块定制协议业务处理 代码 一.Epoll的两种工…...

基于设备指纹识别的反爬虫技术:给设备办 “身份证”

传统的封禁 IP、验证码等反爬虫手段已逐渐失效&#xff0c;基于设备指纹识别的反爬虫技术应运而生&#xff0c;成为守护数据安全的新防线。它如同给每个设备办一张独一无二的 “身份证”&#xff0c;精准区分正常用户与爬虫工具。 一、基础参数采集&#xff1a;构建设备指纹的…...

公开模型一切,优于DeepSeek-R1,英伟达开源Llama-Nemotron家族

在大模型飞速发展的今天&#xff0c;推理能力作为衡量模型智能的关键指标&#xff0c;更是各家 AI 企业竞相追逐的焦点。 但近年来&#xff0c;推理效率已成为模型部署和性能的关键限制因素。 基于此&#xff0c;英伟达推出了 Llama-Nemotron 系列模型&#xff08;基于 Meta …...

CI/CD面试题及答案

一、CI/CD 基础概念 1. 什么是 CI/CD&#xff1f;CI 和 CD 的区别是什么&#xff1f; 答案&#xff1a; CI&#xff08;持续集成&#xff09;&#xff1a;开发人员提交代码后&#xff0c;自动构建并运行测试&#xff0c;确保代码集成无冲突。CD&#xff08;持续交付 / 部署&am…...

解决 Ubuntu DNS 无法解析问题(适用于虚拟机 长期使用)

解决 Ubuntu DNS 无法解析问题 在使用 Ubuntu 虚拟机&#xff08;尤其是在国内&#xff09;时&#xff0c;经常会遇到这样的错误&#xff1a; Temporary failure resolving cn.archive.ubuntu.com但是此时又能成功 ping 通 IP&#xff0c;这说明网络是正常的&#xff0c;问题…...

如何通过C# 获取Excel单元格的数据类型

在处理 Excel 文件时&#xff0c;了解单元格的数据类型有助于我们正确地解析和处理数据。Free Spire.XLS 是一款功能强大且免费的.NET 组件&#xff0c;支持高效地操作 Excel 文件&#xff0c;包括读取单元格类型。本文将详细介绍如何使用 Free Spire.XLS 来获取 Excel 单元格的…...

Spring Boot初级教程:从零搭建企业级Java应用

一、Spring Boot是什么?为什么学它? 定义:Spring Boot是Spring框架的轻量级快速开发工具,基于“约定优于配置”原则,简化Spring应用的搭建与部署。核心优势: 零配置起步:内置Tomcat/Jetty,无需手动部署Web服务器。自动装配:自动扫描依赖、注入Bean,减少XML/注解冗余代…...

IBM BAW(原BPM升级版)使用教程第六讲

一、事件&#xff1a;Undercover Agent 在 IBM Business Automation Workflow (BAW) 中&#xff0c;Undercover Agent (UCA) 是一个非常独特和强大的概念&#xff0c;旨在实现跨流程或系统的事件处理和触发机制。Undercover Agent 主要用于 事件驱动的流程自动化&#xff0c;它…...

[250509] x-cmd 发布 v0.5.11 beta:x ping 优化、AI 模型新增支持和语言变量调整

目录 X-CMD 发布 v0.5.11 beta&#x1f4c3;Changelog&#x1f9e9; ping&#x1f9e9; openai&#x1f9e9; gemini&#x1f9e9; asdf&#x1f9e9; mac✅ 升级指南 X-CMD 发布 v0.5.11 beta &#x1f4c3;Changelog &#x1f9e9; ping 调整 x ping 默认参数为 bing.com&a…...

Web前端VSCode如何解决打开html页面中文乱码的问题(方法2)

Web前端—VSCode如何解决打开html页面中文乱码的问题&#xff08;方法2&#xff09; 1.打开VScode后&#xff0c;依次点击 文件 >> 首选项 >> 设置 2.打开设置后&#xff0c;依次点击 文本编辑器 >> 文件&#xff08;或在搜索框直接搜索“files.autoGuessEnc…...

打造专属AI好友:小智AI聊天机器人详解

打造专属AI好友&#xff1a;小智AI聊天机器人详解 在当下的科技热潮中&#xff0c;AI正迅速改变着我们的生活&#xff0c;成为了科技领域的新宠。而今&#xff0c;借助开源项目的力量&#xff0c;你可以亲手打造一个智能小助手——小智AI聊天机器人。它不仅是一个技术探索的窗…...

Spring,SpringMVC,SpringBoot,SpringCloud的区别

Spring Spring 是一个基础框架&#xff0c;为 Java 应用提供了 IoC&#xff08;控制反转&#xff09;和 AOP&#xff08;面向切面编程&#xff09;功能。其主要特点如下&#xff1a; IoC 容器&#xff1a;借助依赖注入&#xff0c;降低了组件间的耦合度。AOP 支持&#xff1a…...

从投入产出、效率、上手难易度等角度综合对比 pytest 和 unittest 框架

对于选择python作为测试脚本开发的同学来说&#xff0c;pytest和python unittest是必需了解的两个框架。那么他们有什么区别&#xff1f;我们该怎么选&#xff1f;让我们一起来了解一下吧&#xff01; 我们从投入产出、效率、上手难易度等角度综合对比 pytest 和 unittest 框架…...

无人机电池储存与操作指南

一、正确储存方式 1. 储存电量 保持电池在 40%-60% 电量&#xff08;单片电压约3.8V-3.85V&#xff09;存放&#xff0c;避免满电或空电长期储存。 满电存放会加速电解液分解&#xff0c;导致鼓包&#xff1b;**空电**存放可能引发过放&#xff08;电压低于3.0V/片会永久…...

CSS实现图片垂直居中方法

html <div class"footer border-top-row"><div class"footer-row"><span class"footer-row-col01">制单人&#xff1a;{{ printData[pageIndex - 1].rkMaster.makerName}}<img :src"getPersonSignImgSrc(printData[pa…...

多账号管理与自动化中的浏览器指纹对抗方案

多账号管理与自动化中的浏览器指纹对抗方案 在日常的开发工作中&#xff0c;如果你曾涉及自动化脚本、多账号运营、数据抓取&#xff0c;或是在安全研究方向摸爬滚打过&#xff0c;应该对“浏览器指纹识别”这几个字不会陌生。 指纹识别&#xff1a;不是你以为的那种“指纹”…...

[6-1] TIM定时中断 江协科技学习笔记(45个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 TRGO是“Trigger Output”的缩写&#xff0c;中文意思是“触发输出”。在STM32微控制器中&#xff0c;TRGO是一个非常重要的功能&#xff0c;它允许定时器&#xff08;Timer&#xff09;在特定事件发生时输出一个触发信号。这个触发信号可以用…...

Flutter 3.29.3 花屏问题记录

文章目录 Flutter 3.29.3 花屏问题记录问题记录解决尝试解决 Flutter 3.29.3 花屏问题记录 问题记录 flutter版本3.29.3&#xff0c;代码大致为&#xff1a; ShaderMask(shaderCallback: (Rect bounds) {return LinearGradient(begin: Alignment.topCenter,end: Alignment.bo…...

[Windows] 希捷(Seagate)硬盘官方检测工具 - SeaTools(1.4.0.7)

[Windows] 希捷&#xff08;Seagate&#xff09;硬盘官方检测工具 - SeaTools 链接&#xff1a;https://pan.xunlei.com/s/VOPpN9A3Tn_rVktEMu6Lg9q9A1?pwdh8rz# 希望能修复好硬盘...

YOLOv8目标检测性能优化:损失函数改进的深度剖析

文章目录 YOLOv8 简介损失函数在 YOLOv8 中的关键作用SlideLoss 的原理与应用原理代码实例 FocalLoss 分类损失函数的优化原理代码实例 SlideLoss 与 FocalLoss 在 YOLOv8 中的协同作用实验结果与分析 YOLOv8 简介 YOLO&#xff08;You Only Look Once&#xff09;系列目标检测…...

docker 日志暴露方案 (带权限 还 免费 版本)

接到了一个需求&#xff0c;需求的内容是需要将测试环境的容器暴露给我们的 外包同事&#xff0c;但是又不能将所有的容器都暴露给他们。 一开始&#xff0c;我分别找了 Portainer log-pilot dpanel 它们都拥有非常良好的界面和容器情况可视化。 但&#xff0c;缺点是&am…...

水印云:AI赋能,让图像处理变得简单高效

水印云是一款基于超强AI技术的图像处理工具&#xff0c;提供丰富的图像编辑功能&#xff0c;将复杂的图像处理极简化&#xff0c;真正实现简单高效的图像处理。无论是去除水印、智能抠图、添加水印&#xff0c;还是提升画质&#xff0c;水印云都能轻松应对&#xff0c;满足不同…...

使用 ECharts GL 实现交互式 3D 饼图:技术解析与实践

一、效果概览 本文基于 Vue 3 和 ECharts GL&#xff0c;实现了一个具有以下特性的 3D 饼图&#xff1a; 立体视觉效果&#xff1a;通过参数方程构建 3D 扇形与底座动态交互&#xff1a;支持点击选中&#xff08;位移效果&#xff09;和悬停高亮&#xff08;放大效果&#xff…...

allure生成测试报告(搭配Pytest、allure-pytest)

文章目录 前言allure简介allure安装软件下载安装配置环境变量安装成功验证 allure运行流程allure装饰器函数基本说明装饰器函数使用allure.attach 命令行运行利用allure-pytest生成中间结果json 查看测试报告总览页面每个tab页的说明类别页面测试套图表页面时间刻度功能页面包 …...

一场陟遐自迩的 SwiftUI + CoreData 性能优化之旅(下)

概述 自从 SwiftUI 诞生那天起&#xff0c;我们秃头码农们就仿佛打开了一个全新的撸码世界&#xff0c;再辅以 CoreData 框架的鼎力相助&#xff0c;打造一款持久存储支持的 App 就像探囊取物般的 Easy。 话虽如此&#xff0c;不过 CoreData 虽好&#xff0c;稍不留神也可能会…...

java的输入输出模板(ACM模式)

文章目录 1、前置准备2、普通输入输出API①、输入API②、输出API 3、快速输入输出API①、BufferedReader②、BufferedWriter 案例题目描述代码 面试有时候要acm模式&#xff0c;刷惯leetcode可能会手生不会acm模式&#xff0c;该文直接通过几个题来熟悉java的输入输出模板&…...

浏览器自动化与网络爬虫实战:工具对比与选型指南

浏览器自动化与网络爬虫实战&#xff1a;工具对比与选型指南 摘要 在当今数字化时代&#xff0c;浏览器自动化和网络爬虫技术已成为数据收集与测试的重要工具。本文深入剖析了多种主流浏览器自动化工具和爬虫框架的特点、优缺点及其适用场景&#xff0c;包括 Selenium、Puppe…...

“双非” “退伍” “材料” “学验证” 拿到Dream Offer

大家好&#xff0c;我是2024年路科验证V2X春季班的学员。在春季班的课上完后&#xff0c;觉得自己的基础大部分已经被路科给弥补了&#xff0c;但是很多课程中关于框架的搭建和一些细节还是不够扎实&#xff0c;有所欠缺&#xff0c;于是又重修了秋季班的课程。这两次课程给我的…...