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

win10系统下openssl证书生成和单向认证

文章目录

  • 前言
  • 一、安装openssl
  • 二、创建证书目录和必要文件
    • 1、创建sslcertTest文件夹
    • 2、创建openssl.cnf文件
    • 3、创建必要文件
  • 三、创建密钥和证书
    • 1、创建根证书私钥ca.key
    • 2、创建根证书请求文件ca.csr
    • 3、创建自签根证书ca.crt
    • 4、创建服务端私钥server.key
    • 5、创建服务端证书请求文件server.csr
    • 6、创建自签服务端证书server.crt
  • 四、Qt使用QSslSocket实现的单向认证
    • 1、客户端
    • 2、服务端


前言

最近工作中要完成ssl加密啊通信,使用到了openssl,本文主要介绍win10系统下其安装和配置及对应的密钥和证书的生成步骤.

一、安装openssl

下载Win64OpenSSL-1_1_1,双击安装;配置环境变量,如下:
在这里插入图片描述
验证是否安装成功,输入如下命令:

openssl version

在这里插入图片描述

二、创建证书目录和必要文件

1、创建sslcertTest文件夹

我是在C盘下创建的该文件夹.

2、创建openssl.cnf文件

在sslcertTest文件夹下,创建openssl.cnf文件,设置系统变量:
在这里插入图片描述

3、创建必要文件

在sslcertTest文件夹下,创建demoCA文件夹;在该文件夹下,创建index.txt、database.txt、serial文件和newcerts文件夹;其中,serial文件创建后,打开该文件并在第一行编辑输入01
在这里插入图片描述

三、创建密钥和证书

1、创建根证书私钥ca.key

在C:\sslcertTest目录下,进入命令行,命令如下:

openssl genrsa -out ca.key 2048

此命令采用无密码模式,genrsa 表示采用RSA算法生成根证书私钥,2048表示根证书私钥长度,越长越安全.

2、创建根证书请求文件ca.csr

命令如下:

openssl req -new -key ca.key -out ca.csr

以下为demo:

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:TJ
Locality Name (eg, city) []:TJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TJ
Organizational Unit Name (eg, section) []:TJ
Common Name (e.g. server FQDN or YOUR name) []:192.168.10.254
Email Address []:

其中,Country Name 必须填写CN,Common Name 填写服务器IP或域名,否则监测器使用过程中会报SSL错误,尽管忽略错误后可以完成通信。Email Address可以不填;

3、创建自签根证书ca.crt

命令如下:

openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 3650

此处是使用openssl命令完成自签名,证书格式x509,证书有效期10年。

4、创建服务端私钥server.key

命令如下:

openssl genrsa -out server.key 2048

5、创建服务端证书请求文件server.csr

命令如下:

openssl req -new -key server.key -out server.csr

输入如下:

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:TJ
Locality Name (eg, city) []:TJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TJ
Organizational Unit Name (eg, section) []:TJ
Common Name (e.g. server FQDN or YOUR name) []:192.168.10.254
Email Address []:

注意此处,与CA证书请求文件输入一致。

6、创建自签服务端证书server.crt

命令如下:

openssl ca -in server.csr -cert ca.crt -keyfile ca.key -out server.crt -days 3650

此处是自签名,即使用上述自己创建的ca.crt和ca.key,对server.csr进行签名,最终生成一个带有签名的server.crt。
如果你的服务端证书需要别的CA签名机构来签名,则将server.csr请求文件发送给签名机构,签名过程中需要CA的公钥证书和私钥参与,机构签名完成后,返回一个带有CA签名的server.crt文件。
在这里插入图片描述

四、Qt使用QSslSocket实现的单向认证

这里仅展示主要代码:

1、客户端

#include "certificateinfo.h"
#include "sslclient.h"SslClient::SslClient(QWidget *parent): QWidget(parent)
{setupUi();setupSecureSocket();
}SslClient::~SslClient()
{}void SslClient::updateEnabledState()
{/* 不为空或socket处于未连接状态,则unconnected为真 */const bool unconnected = socket->state() == QAbstractSocket::UnconnectedState;/* 更新界面各控件的状态 */hostNameEdit->setReadOnly(!unconnected);hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus);hostNameLabel->setEnabled(unconnected);portBox->setEnabled(unconnected);portLabel->setEnabled(unconnected);connectButton->setEnabled(unconnected && !hostNameEdit->text().isEmpty());const bool connected = socket->state() == QAbstractSocket::ConnectedState;sessionOutput->setEnabled(connected);sessionInput->setEnabled(connected);sessionInputLabel->setEnabled(connected);sendButton->setEnabled(connected);
}/* 点击connect按钮后会执行该函数 */
void SslClient::secureConnect()
{/* 设置SSL协议版本,和服务器相同 */socket->setProtocol(QSsl::TlsV1_2);/* 由于是自签证,所以要设置根证书,用于验证服务器证书,否则客户端不信任服务器 */QList<QSslCertificate> certs = QSslCertificate::fromPath("C:/sslcertTest/ca.crt");socket->setCaCertificates(certs);/* 客户端链接服务器进行SSL握手,当进入加密模式后会发出Encrypted()信号 */socket->connectToHostEncrypted(hostNameEdit->text(), portBox->value());updateEnabledState();
}void SslClient::socketStateChanged(QAbstractSocket::SocketState state)
{if (executingDialog)return;updateEnabledState();if (state == QAbstractSocket::UnconnectedState) {sessionInput->clear();hostNameEdit->setPalette(QPalette());hostNameEdit->setFocus();cipherLabel->setText(tr("<无>"));padLock->hide();}
}void SslClient::socketEncrypted()
{sessionOutput->clear();sessionInput->setFocus();/* 设置lineEdit的背景色 */QPalette palette;palette.setColor(QPalette::Base, QColor(255, 255, 192));hostNameEdit->setPalette(palette);/* 显示加密算法种类 */const QSslCipher cipher = socket->sessionCipher();const QString cipherInfo = QString("%1, %2 (%3/%4)").arg(cipher.authenticationMethod()).arg(cipher.name()).arg(cipher.usedBits()).arg(cipher.supportedBits());cipherLabel->setText(cipherInfo);padLock->show();
}/* 读取数据 */
void SslClient::socketReadyRead()
{appendString(QString::fromUtf8(socket->readAll()));
}/* 发送数据 */
void SslClient::sendData()
{const QString input = sessionInput->text();appendString(input + '\n');socket->write(input.toUtf8() + "\r\n");sessionInput->clear();
}void SslClient::socketError(QAbstractSocket::SocketError)
{if (handlingSocketError)return;handlingSocketError = true;QMessageBox::critical(this, tr("连接错误"), socket->errorString());handlingSocketError = false;
}void SslClient::sslErrors(const QList<QSslError> &errors)
{sslerror->clearError();for (const auto &error : errors)sslerror->showError(error.errorString());executingDialog = true;if (sslerror->exec() == QDialog::Accepted)socket->ignoreSslErrors();executingDialog = false;// did the socket state change?if (socket->state() != QAbstractSocket::ConnectedState)socketStateChanged(socket->state());
}/* 弹出证书内容显示窗口 */
void SslClient::displayCertificateInfo()
{CertificateInfo info;info.setCertificateChain(socket->peerCertificateChain());info.exec();
}void SslClient::setupUi()
{gridLayout = new QGridLayout;hostNameEdit = new QLineEdit;hostNameLabel = new QLabel;portBox = new QSpinBox;portLabel = new QLabel;sessionLayout = new QHBoxLayout;label = new QLabel;connectButton = new QPushButton;labelLayout = new QHBoxLayout;cipherLabel = new QLabel;cipherText = new QLabel;sessionOutput = new QTextEdit;inputLayout = new QHBoxLayout;sendButton = new QPushButton;sessionInput = new QLineEdit;sessionInputLabel = new QLabel;mainLayout = new QVBoxLayout;hostNameLabel->setText("主机名称:");portLabel->setText("端口:");hostNameEdit->setText("192.168.3.140");portBox->setRange(0,65535);portBox->setValue(5001);gridLayout->addWidget(hostNameLabel,0,0);gridLayout->addWidget(hostNameEdit,0,1);gridLayout->addWidget(portLabel,1,0);gridLayout->addWidget(portBox,1,1);label->setText("激活会话");connectButton->setText("连接到主机");sessionLayout->addWidget(label);sessionLayout->addWidget(connectButton);cipherLabel->setText("<加密算法>");cipherText->setText("<无>");labelLayout->addWidget(cipherLabel);labelLayout->addStretch();labelLayout->addWidget(cipherText);sessionInputLabel->setText("输入:");sendButton->setText("发送");inputLayout->addWidget(sessionInputLabel);inputLayout->addWidget(sessionInput);inputLayout->addWidget(sendButton);hostNameEdit->setSelection(0, hostNameEdit->text().size());sessionOutput->setHtml(tr("&lt;无连接&gt;"));mainLayout->addLayout(gridLayout);mainLayout->addLayout(sessionLayout);mainLayout->addLayout(labelLayout);mainLayout->addWidget(sessionOutput);mainLayout->addLayout(inputLayout);setLayout(mainLayout);connect(hostNameEdit, SIGNAL(textChanged(QString)),this, SLOT(updateEnabledState()));connect(connectButton, SIGNAL(clicked()),this, SLOT(secureConnect()));connect(sendButton, SIGNAL(clicked()),this, SLOT(sendData()));sslerror = new SslErrors;connect(sslerror,&SslErrors::sigDisplayCertificateInfo,this,&SslClient::displayCertificateInfo);setWindowTitle("SSL通信客户端");padLock = new QToolButton;/* 设置按钮图标 */padLock->setIcon(QIcon(":/encrypted.png"));connect(padLock, SIGNAL(clicked()), this, SLOT(displayCertificateInfo()));#if QT_CONFIG(cursor)padLock->setCursor(Qt::ArrowCursor);
#endif/* 设置提示信息 */padLock->setToolTip(tr("显示详细加密信息."));/* 调整按钮大小和焦点 */const int extent = hostNameEdit->height() - 2;padLock->resize(extent, extent);padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);/* 界面布局 */QHBoxLayout *layout = new QHBoxLayout(hostNameEdit);layout->setMargin(hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));layout->setSpacing(0);layout->addStretch();layout->addWidget(padLock);hostNameEdit->setLayout(layout);padLock->hide();resize(300,300);
}void SslClient::setupSecureSocket()
{/* socket为空则创建 */if (socket)return;socket = new QSslSocket(this);connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));connect(socket, SIGNAL(encrypted()),this, SLOT(socketEncrypted()));connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(socketError(QAbstractSocket::SocketError)));connect(socket, SIGNAL(sslErrors(QList<QSslError>)),this, SLOT(sslErrors(QList<QSslError>)));connect(socket, SIGNAL(readyRead()),this, SLOT(socketReadyRead()));
}void SslClient::appendString(const QString &line)
{/* 设置光标 */QTextCursor cursor(sessionOutput->textCursor());cursor.movePosition(QTextCursor::End);cursor.insertText(line);/* 将滚动条设置到最后一行 */sessionOutput->verticalScrollBar()->setValue(sessionOutput->verticalScrollBar()->maximum());
}

2、服务端

#include "sslserver.h"
#include <QDebug>
#include <QThread>
#include <QMessageBox>sslserver::sslserver(QObject *parent) : QTcpServer(parent)
{
}sslserver::~sslserver()
{
}/* 当有客户端连接上服务器时会调用该函数 */
void sslserver::incomingConnection(qintptr socketDescriptor)
{sock = new QSslSocket;connect(sock,SIGNAL(readyRead()),this,SLOT(readyRead()));connect(sock,SIGNAL(encrypted()),this,SLOT(encrypted()));/* 设置根证书,握手时客户端会接收到根证书 QList<QSslCertificate> certs = QSslCertificate::fromPath("C:/sslcertTest/ca.crt");sock->setCaCertificates(certs);*//* 设置本地的服务器证书,证书中的Common Name要写服务器地址 */sock->setLocalCertificate("C:/sslcertTest/server.crt");/* 当服务器秘钥有密码时 *///QString passwd = "1234";//sock->setPrivateKey("C:/sslcertTest/server.key",QSsl::Rsa,QSsl::Pem,passwd.toLocal8Bit());/* 如果服务器秘钥没有密码 */sock->setPrivateKey("C:/sslcertTest/server.key");/* 设置ssl通信协议版本 */sock->setProtocol(QSsl::TlsV1_2);/* 使用的加密算法 *//* 默认就是这个"DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA" */sock->setCiphers(QSslSocket::supportedCiphers());//sock->setCiphers("RC4-SHA");if(sock->setSocketDescriptor(socketDescriptor)){/* SSL握手 */sock->startServerEncryption();}else{delete sock;}
}void sslserver::startssl()
{/* 允许所有地址,监听端口5001,设置这个端口为了排除其他的干扰*/listen(QHostAddress::Any,5001);  //
}void sslserver::readyRead()
{if(display){display->append(sock->readAll());}
}void sslserver::encrypted()
{if(display){display->append("进入加密模式");}
}void sslserver::setDisplayContrl(QTextEdit *disp)
{display = disp;
}

相关文章:

win10系统下openssl证书生成和单向认证

文章目录 前言一、安装openssl二、创建证书目录和必要文件1、创建sslcertTest文件夹2、创建openssl.cnf文件3、创建必要文件 三、创建密钥和证书1、创建根证书私钥ca.key2、创建根证书请求文件ca.csr3、创建自签根证书ca.crt4、创建服务端私钥server.key5、创建服务端证书请求文…...

动态规划的解题思想

1. 从斐波那契数列说起 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c; &#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0, F(2) 1 F&#xff08;n&#xff09; F&…...

OpenCV结构分析与形状描述符(10)检测并提取轮廓函数findContours()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在二值图像中查找轮廓。 该函数使用算法 253从二值图像中检索轮廓。轮廓是有用的工具&#xff0c;可用于形状分析和对象检测与识别。参见 OpenC…...

HBase 源码阅读(二)

衔接 在上一篇文章中&#xff0c;HMasterCommandLine类中在startMaster();方法中 // 这里除了启动HMaster之外&#xff0c;还启动一个HRegionServerLocalHBaseCluster cluster new LocalHBaseCluster(conf, mastersCount, regionServersCount,LocalHMaster.class, HRegionSer…...

深度学习每周学习总结N9:transformer复现

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 多头注意力机制前馈传播位置编码编码层解码层Transformer模型构建使用示例 本文为TR3学习打卡&#xff0c;为了保证记录顺序我这里写…...

数据结构与算法(3)栈和队列

1.前言 哈喽大家好啊&#xff0c;今天博主继续为大家带来数据结构与算法的学习笔记&#xff0c;今天是关于栈和队列&#xff0c;未来博主会将上一章《顺序表与链表》以及本章《栈与队列》做专门的习题应用专题讲解&#xff0c;都会很有内容含量 &#xff0c;欢迎大家多多支持&…...

11、Django Admin启用对计算字段的过滤

重新定义admin.py中的Hero管理模型如下&#xff1a; admin.register(Hero) class HeroAdmin(admin.ModelAdmin):list_display ("name", "is_immortal", "category", "origin", "is_very_benevolent")list_filter ("…...

xxl-job升级到springboot3.0 导致页面打不开报错)问题

原因&#xff1a;springboot3.0 因为移除了jsp 导致xxl-job不能访问&#xff0c;解决方法如下 1、修改PermissionInterceptor拦截器 package com.xxl.job.admin.controller.interceptor;import com.xxl.job.admin.controller.annotation.PermissionLimit; import com.xxl.job.…...

栈和队列.

目录 1. 栈&#xff08;Stack&#xff09; 2. 栈的模拟实现 3. 栈的应用场景 4. 队列&#xff08;Queue&#xff09; 5. 队列的模拟实现 6. 循环队列 7. 双端队列&#xff08;Deque&#xff09; 8. 面试题 1. 栈&#xff08;Stack&#xff09; 栈&#xff1a;一种特殊…...

Parallel.ForEach - 并行处理

Parallel.ForEach 是 C# 中 System.Threading.Tasks.Parallel 类提供的一个方法&#xff0c;用于并行地迭代集合中的每一个元素。Parallel.ForEach 方法允许多个线程同时处理集合中的元素&#xff0c;从而提高程序的执行效率&#xff0c;特别是在处理大量数据或执行耗时任务时。…...

【MySQL】初识MySQL—MySQL是啥,以及如何简单操作???

前言&#xff1a; &#x1f31f;&#x1f31f;本期讲解关于MySQL的简单使用和注意事项&#xff0c;希望能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;http://t.csdnimg.cn/wwaqe &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 目…...

LLM应用实战: 产业治理多标签分类

数据介绍 标签体系 产业治理方面的标签体系共计200个&#xff0c;每个标签共有4个层级&#xff0c;且第3、4层级有标签含义的概括信息。 原始数据 企业官网介绍数据&#xff0c;包括基本介绍、主要产品等 企业专利数据&#xff0c;包括专利名称和专利摘要信息&#xff0c;且专…...

下载Mongodb 4.2.25 版本教程

1、MongoDB 安装包的下载链接 Download MongoDB Community Server | MongoDB 进入如下截图&#xff1a; 2、查找历史版本 往下拉&#xff0c;点击“...”,找到”Archived releases”,点击进入 、 3、下载Mongodb 4.2.25 版本 找到如下图4.2.25版本下载链接&#xff0c;点击就可…...

docker拉取redis5.0.5并建立redis集群

1.配置文件 mkdir -p redis-cluster/7001/ mkdir -p redis-cluster/7002/ mkdir -p redis-cluster/7003/ mkdir -p redis-cluster/7004/ mkdir -p redis-cluster/7005/ mkdir -p redis-cluster/7006/cd redis-clustervim 7001/redis.confbind 0.0.0.0port 7001cluster-enabled…...

React16新手教程记录

文章目录 前言一些前端面试题1. 搭建项目1. 1 cdn1. 2 脚手架 2. 基础用法2.1 表达式和js语句区别&#xff1a;2.2 jsx2.3 循环map2.4 函数式组件2.5 类式组件2.6 类组件点击事件2.6.1 事件回调函数this指向2.6.2 this解决方案2.6.2.1 通过bind2.6.2.2 箭头函数&#xff08;推荐…...

怎么摆脱非自然链接?

什么是非自然链接&#xff1f; 非自然链接是人为创建的链接&#xff0c;用于操纵网站在搜索引擎中的排名。非自然链接违反了Google 的准则&#xff0c;网站可能会因此受到惩罚。 它们不是由网站所有者编辑放置或担保的。示例包括带有过度优化锚文本的链接、通过 PR 的广告、嵌…...

【2024数模国赛赛题思路公开】国赛B题第二套思路丨附可运行代码丨无偿自提

2024年数模国赛B题解题思路 B 题 生产过程中的决策问题 一、问题1解析 问题1的任务是为企业设计一个合理的抽样检测方案&#xff0c;基于少量样本推断整批零配件的次品率&#xff0c;帮助企业决定是否接收供应商提供的这批零配件。具体来说&#xff0c;企业需要依据两个不同…...

P1166 打保龄球

共可以投 1 局 一局10轮 在一局中&#xff0c;一共有十个柱&#xff0c;会出现很多种情况。 第1次把10个 打倒全部 >> 分数10后2次得分 --若是第10轮则还需另加两次滚球&#xff1b; 没全部打倒 >> 第2次把剩下的 打倒 >&g…...

[数据集][目标检测]西红柿成熟度检测数据集VOC+YOLO格式3241张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3241 标注数量(xml文件个数)&#xff1a;3241 标注数量(txt文件个数)&#xff1a;3241 标注…...

数仓工具—Hive语法之URL 函数

hive—语法—URL 函数 业务需求中,我们经常需要对用户的访问、用户的来源进行分析,用于支持运营和决策。例如我们经常对用户访问的页面进行统计分析,分析热门受访页面的Top10,观察大部分用户最喜欢的访问最多的页面等: 又或者我们需要分析不同搜索平台的用户来源分析,统…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...