• 🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用
  • 🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】
  • 🍅 玩转CANoe,博客目录大全,点击跳转👉

目录

  • 📙 1 基础知识储备
    • 🍅1.1 OpenSSL库下载安装
    • 🍅1. 2 AES 加密算法
      • 1.2.1、主要特点
      • 1.2.2、AES 加密支持的不同模式
      • 1.2.3、填充模式
      • 1.2.4、AES 密钥大小
    • 🍅1.3 在Visual studio 环境中配置OpenSSL
      • 1.3.1 新建 visual studio 控制台应用
      • 1.3.2 配置OpenSSL环境
  • 📙 2、AES CBC 算法测试
  • 📙 3、生成 Seed&Key DLL
  • 📙 4、CANoe中配置Seed&Key DLL
  • 📙 5、不使用诊断控制台计算AES
  • 📙 6、CAPL内置AES函数
  • 📙 7、源码获取


📙 1 基础知识储备

🍅1.1 OpenSSL库下载安装

OpenSSL 是一个开源的软件库,主要用于实现安全通信协议和加密算法。提供广泛的加密算法实现,包括对称加密(如 AES)、非对称加密(如 RSA)、哈希函数(如 SHA)等,支持 SSL/TLS 协议,用于实现安全的网络通信,提供证书管理功能,支持 X.509 证书的生成、验证和管理。主要组件:

  • libcrypto:加密算法库,提供各种加密、解密、签名、验证等基础功能
  • libssl:SSL/TLS 协议实现库,用于安全通信
  • openssl 命令行工具:用于执行各种加密操作、证书管理等任务

OpenSSL下载链接:https://slproweb.com/products/Win32OpenSSL.html

  • 用户可以根据实际需要选择64或者32位版本进行安装,在Visual studio中编译的时候也要选择对应的版本来进行编译,
    同时也需与CANoe的RT Kernel的版本(32bit/64bit)保持一致。
  • 本文档使用64位的OpenSSL v3.4.1为例进行介绍,不同版本都会有相应的API改变,可能导致本文示例代码报错等。
    在这里插入图片描述
  • 我这里64/32位的都下载下来了,然后点击Win64OpenSSL-3_4_1.exe就可以安装了,根据需要把安装路径改下,其它直接点下一步即可。
    在这里插入图片描述
  • 安装完成后,记住这个安装路径,其中includelib文件夹待会要用。
    在这里插入图片描述
  • 安装完成后,在CMD中输入openssl,如下图就说明安装成功了。
    在这里插入图片描述

🍅1. 2 AES 加密算法

1.2.1、主要特点

  • 称密钥算法:AES 是一种对称密钥算法,这意味着加密和解密使用相同的密钥。这种特性使得加密和解密的操作相对简单且高效,在密钥管理妥善的情况下,能确保数据的保密性。

  • 分组密码:AES 对固定大小的数据块进行操作,是分组密码类型。其标准块大小为 128 位,这种以固定块大小处理数据的方式有助于保证加密过程的规范性和安全性。

  • 密钥长度:AES 支持 128、192 和 256 位的密钥长度。密钥长度是决定加密强度的重要因素,一般来说,密钥越长,加密越强。较长的密钥意味着更多的密钥组合可能性,从而增加了破解的难度。

  • 安全性:AES 被广泛认为是非常安全的加密算法,并在各种安全协议和应用程序中有着广泛应用。其安全性经过了长期的实践检验和理论分析,能够有效抵御多种攻击手段,保护数据安全。

1.2.2、AES 加密支持的不同模式

  • ECB(Electronic Code Book)模式:这是最简单的加密方式,加密时不需要 IV(偏移量)。输入的明文会被分成块,每个块用提供的密钥进行加密,其特点是相同的明文块被加密成相同的密文块。
  • CBC(密码块链接)模式:强烈推荐使用此模式,它是分组密码加密的一种高级形式。它需要 IV 来使每条消息都具有唯一性,这意味着相同的纯文本块被加密为不同的密码文本块。因此,与 ECB 模式相比,它提供了更强大的加密,但速度相对稍慢。若没有输入 IV,则此处将使用 CBC 模式的默认值,并且默认为从零开始的字节[16]。
  • CTR(计数器)模式:CTR 模式(CM)也称为整数计数器模式(ICM)和分段整数计数器模式(SIC)。计数器模式将分组密码转换为流密码。CTR 模式具有与 OFB 类似的特性,但也允许在解密过程中具有随机访问属性。CTR 模式非常适合在多处理器机器上运行,其中可以并行加密块。
  • GCM(Galois/Counter 模式):GCM 是一种对称密钥分组密码操作模式,使用通用哈希来提供经过认证的加密。GCM 被认为比 CBC 模式更安全,因为它具有内置的身份验证和完整性检查,并且因其性能优势而得到广泛使用。

1.2.3、填充模式

  1. PKCS#5 填充(PKCS#5 Padding)
    PKCS#5 是为 8 字节块大小设计的填充方案。不过在实际应用中,当 AES 块大小为 16 字节时,通常使用的是 PKCS#7 填充。其填充规则为:在数据末尾添加字节,每个填充字节的值等于需要填充的字节数。例如,若数据长度比块大小少 3 字节,就添加 3 个值为 0x03 的字节;若数据长度恰好是块大小的整数倍,会添加一个完整块,块内所有字节值为块大小数值(AES 中为 0x10)。

  2. PKCS#7 填充(PKCS#7 Padding)
    PKCS#7 是 PKCS#5 的扩展,支持任意块大小。在 AES 加密中,PKCS#7 填充和 PKCS#5 填充在行为上一致。它是最常用的填充模式之一,能确保数据长度为块大小的整数倍。

  3. ISO 10126 填充(ISO 10126 Padding)
    此填充模式在数据末尾添加填充字节,除最后一个字节外,其他填充字节填充随机值,最后一个字节的值为需要填充的字节数。例如,若需填充 5 个字节,前 4 个字节是随机值,最后一个字节为 0x05。

  4. Zero Padding
    这种填充模式在数据末尾填充 0 字节,直到数据长度达到块大小的整数倍。不过它存在一个问题,若原始数据末尾本身就有 0 字节,解密时难以区分哪些 0 字节是原始数据,哪些是填充的,所以使用时需要额外处理。

  5. No Padding
    该模式要求输入数据长度必须是块大小的整数倍,若不满足则会报错。在实际应用中,需要提前确保数据长度符合要求,使用场景相对受限。

1.2.4、AES 密钥大小

  • IV 即初始化向量(Initialization Vector),是一个固定长度的随机值,无论是 AES 256、AES 192 还是 AES 128,其在使用需要初始化向量(IV)的加密模式(如 CBC、CFB、OFB 等)时,IV 的字节大小都是 128 比特(即 16 字节)
  • 原因
    这是因为IV 的长度取决于加密算法的块大小,而不是密钥长度。AES 是一种分组加密算法,其块大小固定为 128 比特,与选择使用 128 比特、192 比特还是 256 比特的密钥无关。因此,在使用需要 IV 的加密模式时,IV 的长度必须和块大小一致,也就是 128 比特。
  • 作用
    IV 的主要作用是增加加密的随机性和安全性。在像 CBC 这样的模式中,每个明文块在加密前会与前一个密文块进行异或操作,第一个明文块则与 IV 异或。使用不同的 IV 可以使相同的明文在相同密钥下产生不同的密文,防止攻击者通过分析密文模式来破解加密信息。

🍅1.3 在Visual studio 环境中配置OpenSSL

  • 博主这里使用的是visual studio 2022 社区版

1.3.1 新建 visual studio 控制台应用

  • 这里我们先创建一个 控制台应用 测试下OpenSSL的应用,等调试通过后,再创建动态库工程

在这里插入图片描述
在这里插入图片描述

1.3.2 配置OpenSSL环境

  • 选择工程>>属性
    在这里插入图片描述

  • 将OpenSSL的includelib目录添加到 VC++目录下的 外部包含目录库目录
    在这里插入图片描述

  • 连接器>>输入>>附加依赖项 选项中填入 libcrypto.lib;libssl.lib;
    在这里插入图片描述

  • 在默认文件的头部引入 #include <openssl/evp.h>下图配错),并且执行程序,不报错,就说明我们OpenSSL库的环境配置成功了。
    在这里插入图片描述

📙 2、AES CBC 算法测试

  • 不同的厂商选择的加密算法可能都不一样,但是只要是OpenSSL的支持算法,都可以参考下面代码示例仿写。
  • 下面是 AES CBC 加密解密的示例**,用于 Seed&Key DLL的AES算法一般要求加密的数据都是16的倍数,如果您的密钥不是16的整数倍,请根据需求填充至16的整数倍**,核心参数是IV和Key参数值。
#include <iostream>
#include <openssl/evp.h>
#include <cstring>
#include <windows.h>// AES CBC 加密
void aes_cbc_encrypt(const unsigned char plaintext[], size_t length,unsigned char ciphertext[],const unsigned char key[],const unsigned char iv[]) {EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();int len;int ciphertext_len;// 初始化加密操作,设置无填充模式EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);EVP_CIPHER_CTX_set_padding(ctx, 0);  // 禁用填充// 加密EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, length);ciphertext_len = len;// 完成加密EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);ciphertext_len += len;EVP_CIPHER_CTX_free(ctx);
}// AES CBC 解密
void aes_cbc_decrypt(const unsigned char ciphertext[], size_t length,unsigned char plaintext[],const unsigned char key[],const unsigned char iv[]) 
{EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();int len;int plaintext_len;// 初始化解密操作,设置无填充模式EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);EVP_CIPHER_CTX_set_padding(ctx, 0);  // 禁用填充// 解密EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, length);plaintext_len = len;// 完成解密EVP_DecryptFinal_ex(ctx, plaintext + len, &len);plaintext_len += len;EVP_CIPHER_CTX_free(ctx);
}int main() 
{// 示例密钥和IV(必须是16字节)unsigned char key[16] ={ 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x10,0x21,0x31,0x41,0x51,0x61,0x71 };unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };// 示例明文const unsigned char plaintext[64] = { 0xF6, 0xFE, 0xEB, 0x57, 0xFB, 0xAD, 0xBA, 0xE6, 0x67, 0xB9, 0x9C, 0x2E, 0xDF, 0xF5, 0xE2, 0x42,0x5F, 0x9B, 0x88, 0x71, 0xF5, 0x77, 0xC9, 0xD3, 0xD1, 0x5E, 0xDB, 0x77, 0xDE, 0xE9, 0xAD, 0x97, 0x7F, 0xE7, 0x91, 0x59, 0xB0, 0xEF, 0x2B, 0x4F, 0x7B, 0x6B, 0x2B, 0x6A, 0xF5, 0xFF, 0xB3, 0xD6, 0xF8, 0x9F, 0xBF, 0x85, 0x6F, 0xF3, 0xA1, 0xFD, 0xED, 0xB7, 0x3B, 0xF9, 0x71, 0xEF, 0xAA, 0x59 };size_t length = 64;char unsigned ciphertext[64] ;char unsigned decryptedText[64] ;std::cout << "原始加密数据: ";for (size_t i = 0; i < length; ++i) {printf("%02X ", plaintext[i]);}std::cout << "\n";// 加密aes_cbc_encrypt(plaintext, length,ciphertext, key, iv);// 打印加密后的数据std::cout << "加密后的数据: ";for (size_t i = 0; i < length; ++i) {printf("%02X ", ciphertext[i]);}std::cout << "\n";// 解密aes_cbc_decrypt(ciphertext, length,decryptedText, key, iv);std::cout << "解密后的数据: ";for (size_t i = 0; i < length; ++i) {printf("%02X ", decryptedText[i]);}std::cout << "\n";return 0;
}
  • 测试结果 如图,可以正常的加密和解密。

在这里插入图片描述

📙 3、生成 Seed&Key DLL

在如下路径下找到Vector官方自带的创建Seed&Key DLL的示例代码

C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 16.4.4\CAN\Diagnostics\UDSSystem\SecurityAccess\Sources\KeyGenDll_GenerateKeyEx
  • 第一步,我们把如下两个文件拷贝到AES_CBC文件夹下。

在这里插入图片描述

  • 第二步,把GenerateKeyExImpl.cpp文件中代码拷贝到AES_CBC.cpp文件中,引入KeyGenAlgoInterfaceEx.h头文件,并根据您的加密算法完善GenerateKeyEx函数。

  • 第三步,把属性的配置类型改为 动态库(.dll)

在这里插入图片描述

  • 第四步,点击 生成>>生成解决方案 ,即可生成 Seed&Key DLL。

在这里插入图片描述

📙 4、CANoe中配置Seed&Key DLL


切换CANoe RT kernel

  • CANoe版本低于13,建议使用32bit的库进行开发。
  • CANoe版本高于13,切换RT Kernel 32bit 和64 bit 路径如下

在这里插入图片描述

  • 在诊断控制台中加载刚才生成的dll即可使用。

在这里插入图片描述

  • 在诊断控制台中可以实现AES解锁

在这里插入图片描述

  • 用户也可以在CAPL脚本中也可通过内置函数DiagGenerateKeyFromSeed 实现计算AES,当用户调用DiagGenerateKeyFromSeed函数时,CANoe内部机制会去调用诊断控制台中加载的AES_CBC.dll中的GenerateKeyEx接口,从而实现加密计算。
long Secuiry_Cal_Key(byte gSecurityLevel,byte seed[],byte seedkey[],byte size)  
{long i, resSize,ret; char gVariant[200]    = "Variant1";char gOption[200]     = "option";byte gKeyArray[255];int  gMaxKeyArraySize = 255;dword gActualSize     = 0;//计算 Key      ret =  DiagGenerateKeyFromSeed (seed, size , gSecurityLevel, gVariant, gOption, seedkey, gMaxKeyArraySize, gActualSize);   //generate key                     return ret; 
}

📙 5、不使用诊断控制台计算AES

  • 上面生成的SeedKey.dll只适用于在CANoe软件中加载了PDX/CDD等诊断数据库的情况下使用。且该dll在CAPL文件中无法通过#pragma library("xxxx.dll")语法加载。如果用户不使用CANoe的诊断控制台,只想通过CAPL实现AES的加密算法,则需要通过 C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 16.7.5\Programming\CAPLdll 路径下示例工程的语法方式创建DLL。

  • 如下面CAPL代码示例,通过visual studio 封装的一个函数aes_cbc_encrypt用于计算seed生成Key,该函数的函数参数解释如下:

    • iSeedArray : 用于计算的seed数组
    • Length:seed数组长度
    • ioKeyArray:返回的密钥数组
    • Key : AES算法加密密钥
    • IV:AES算法初始向量数组
    • error_info:函数报错信息
    • error_info_size:函数报错信息字符串长度
    • 返回值:返回的密钥数组长度
/*@!Encoding:65001*/
includes
{#if X64#pragma library("X64\AES_CBC_X64.dll")#else#pragma library("X86\AES_CBC_X86.dll")#endif
}on key '1'
{byte _key[16] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x10,0x21,0x31,0x41,0x51,0x61,0x71 };byte _iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };byte Seed[64] =  { 0xF6, 0xFE, 0xEB, 0x57, 0xFB, 0xAD, 0xBA, 0xE6, 0x67, 0xB9, 0x9C, 0x2E, 0xDF, 0xF5, 0xE2, 0x42,0x5F, 0x9B, 0x88, 0x71, 0xF5, 0x77, 0xC9, 0xD3, 0xD1, 0x5E, 0xDB, 0x77, 0xDE, 0xE9, 0xAD, 0x97, 0x7F, 0xE7, 0x91, 0x59, 0xB0, 0xEF, 0x2B, 0x4F, 0x7B, 0x6B, 0x2B, 0x6A, 0xF5, 0xFF, 0xB3, 0xD6, 0xF8, 0x9F, 0xBF, 0x85, 0x6F, 0xF3, 0xA1, 0xFD, 0xED, 0xB7, 0x3B, 0xF9, 0x71, 0xEF, 0xAA, 0x59 };byte outKey[64];char err_info[0x256];long outKey_Size,i;outKey_Size = aes_cbc_encrypt(Seed,elcount(Seed),outKey,_key,_iv,err_info,elcount(err_info));write("retVal = %d",outKey_Size);if(outKey_Size!=-1){for(i = 0;i<outKey_Size;i++)write("outKey[%d] = 0x%X",i,outKey[i]);}
}
  • 测试结果如下:

在这里插入图片描述

📙 6、CAPL内置AES函数

  • CANoe软件内置了一个SecMgrCANoeClient.dll文件,该文件封装了一些互联网常用的加密算法,如RSA/AES/CMAC,以及X509证书相关等,该文件的目录如下(以CANoe 16 安装目录为例):
    在这里插入图片描述

  • 该DLL内,封装了很多的函数,本文用到了AES-128-CBC,就以这两个函数为例,讲解下如何使用
    在这里插入图片描述

  • 在使用的Test/simulation 节点中加载SecMgrCANoeClient.dll文件
    在这里插入图片描述

  • 在使用的Test/simulation 节点的CAPL文件的测试代码如下:
    Note :
    1、如果运行脚本导致软件崩溃的话,在 includes代码中再引用一遍SecMgrCANoeClient.dll函数
    2、(dword outKey_Size = elcount(outKey) + 16 )为什么这段代码要加 16 ,参考下文的帮助文档

/*@!Encoding:65001*/
includes
{ 
//  #pragma library("C:\ProgramData\Vector\Security Manager\General\Binaries\SecMgrCANoeClient\CANoe_13.0.117\Windows-x64\SecMgrCANoeClient.dll")
}on key '1'
{byte _key[16] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x10,0x21,0x31,0x41,0x51,0x61,0x71 };byte _iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };byte Seed[64] =  { 0xF6, 0xFE, 0xEB, 0x57, 0xFB, 0xAD, 0xBA, 0xE6, 0x67, 0xB9, 0x9C, 0x2E, 0xDF, 0xF5, 0xE2, 0x42,0x5F, 0x9B, 0x88, 0x71, 0xF5, 0x77, 0xC9, 0xD3, 0xD1, 0x5E, 0xDB, 0x77, 0xDE, 0xE9, 0xAD, 0x97, 0x7F, 0xE7, 0x91, 0x59, 0xB0, 0xEF, 0x2B, 0x4F, 0x7B, 0x6B, 0x2B, 0x6A, 0xF5, 0xFF, 0xB3, 0xD6, 0xF8, 0x9F, 0xBF, 0x85, 0x6F, 0xF3, 0xA1, 0xFD, 0xED, 0xB7, 0x3B, 0xF9, 0x71, 0xEF, 0xAA, 0x59 };byte outKey[64];long Ret,i;dword outKey_Size = elcount(outKey) + 16 ;Ret = SecurityLocalEncryptAES128CBC(_key,elcount(_key),Seed,elcount(Seed),_iv,elcount(_iv),outKey,outKey_Size);write("outKey_Size = %d,Ret = %d",outKey_Size,Ret);if(Ret == 1){for(i = 0;i<elcount(outKey);i++)write("outKey[%d] = 0x%X",i,outKey[i]);}
}
  • 测试结果如下:
    在这里插入图片描述
  • SecurityLocalEncryptAES128CBC函数的help文档解释如下:
    使用该函数需要注意:这个函数默认是采用PKCS5方式填充的。输入cipheredDataLength参数的长度必须比cipheredData数组大小 大16字节,否则函数返回值为0.
    在这里插入图片描述

📙 7、源码获取

23

  • 如果你只需要在CANoe软件的诊断控制台中使用seedKey.dll,则可以下载下面的源码

    • 在CANoe诊断控制台中可用的,用于实现AES-CBC 128 加密运算的C++创建DLL程序源码
  • 如果你只需要在CAPL脚本实现AES的加密运算,不需要在CANoe的诊断配置中加载CDD/PDX等诊断数据库,则使用CAPL内置的函数即可,如果CAPL内置函数没有你需要的加密算法,则可以下载下面的源码进行适配

    • 在CAPL脚本中可用的,用于实现AES-CBC 128 加密运算的C++创建DLL程序源码
  • 下面源码包含诊断控制台和CAPL中可用的源码

    • CANoe诊断控制台和CAPL脚本中都可使用的,两个工程源码
  • 基于以下工程源码,均已配置好,无需再下载安装OpenSSL库,如果下载源码后,C++配置有问题可Q我解决!

7

  • 🚩要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    18

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85772.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85772.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/85772.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进程间通信、线程间通信

进程间通信、线程间通信 进程间通行&#xff08;Inter-Process Communication&#xff0c; IPC&#xff09;和线程间通信&#xff08;Thread Communication&#xff09;的方式不完全相同&#xff0c;因为进程和线程的运行环境和特性不同 进程和线程的本质区别 进程 进程是操…

【FPGA学习】FPGA入门学习即数字逻辑复习

前言&#xff1a;最近开始学习FPGA了&#xff0c;希望通过博客记录下每一次学习的过程&#xff0c;与大家共勉。 目录 一、组合逻辑电路的设计&#xff08;工程学习引入&#xff09; 二、3-8译码器设计、下载和功能演示&#xff08;在的8段数码管显示&#xff09; 2.1 Logs…

ffmpeg python rgba图片合成 4444格式mov视频,保留透明通道

def convert_pngs_to_mov(input_pattern, output_path, frame_rate30):"""将BGRA四通道PNG序列转换为ProRes 4444编码的MOV视频&#xff08;保留透明通道&#xff09;参数:input_pattern: PNG序列路径模式&#xff08;如&#xff1a;"/path/to/frames/fram…

Java 实现 PDF 转图片功能:实战教程 + 场景解析

作者:云起川南|专注 Java 实战与自动化集成 在 PDF 文档处理的各类业务场景中,“将 PDF 页面转为图片”是一个高频、刚需的功能,广泛应用于 预览展示、文件归档、图片加密水印、OCR 文本识别 等系统中。 本文将带你一步一步实战如何使用 Java 实现 PDF 转图片 功能,使用开…

面试题-有个对象key全部是string,值全部是number要定义他,不使用interface和type如何定义

在 TypeScript 里&#xff0c;若要定义一个键为string类型、值为number类型的对象&#xff0c;并且不使用interface和type&#xff0c;可以采用以下几种方式&#xff1a; 1. 内联类型注解&#xff08;Inline Type Annotation&#xff09; 直接在变量声明时使用索引签名进行类…

领域驱动设计(DDD)【3】之事件风暴

文章目录 说明一 事件风暴理论知识1.1 事件风暴的核心目标1.2事件风暴的关键步骤1.2.1 准备工作1.2.2 核心流程1.2.3 事件风暴的输出 1.3 事件风暴的优势1.4 常见问题Q1&#xff1a;事件风暴适合所有项目吗&#xff1f;Q2&#xff1a;事件风暴后如何落地&#xff1f;Q3&#xf…

Vue3中监听 Ref 类型的数字数组

在 Vue 3 中&#xff0c;监听一个 Ref 类型的数字数组&#xff08;如 ref<number[]>([])&#xff09;时&#xff0c;根据需求的不同&#xff0c;有几种监听方式&#xff1a; 1. 监听整个数组的引用变化 当整个数组被重新赋值时触发&#xff1a; typescript 复制 下载…

PoolThreadCache 类的结构和源码实现

PoolThreadCache 在 Netty 的内存池中扮演着线程本地缓存的角色。它的主要目的是减少线程在分配内存时对全局 PoolArena 的竞争&#xff0c;通过缓存一部分最近释放的内存块&#xff0c;使得同一线程后续申请相同规格的内存时能够快速获取&#xff0c;从而提高分配效率。 下面…

Linux中的阻塞信号与信号原理

在Linux操作系统中&#xff0c;信号&#xff08;Signal&#xff09;是进程间通信和进程控制的核心机制之一。信号是一种异步通知机制&#xff0c;可以向进程发送异步事件通知&#xff0c;以便进程能够处理系统级别的事件。本文将详细探讨Linux中的信号原理&#xff0c;重点讲解…

QT学习教程(三十五)

事件处理&#xff08;- Event Processingn&#xff09; 事件是视窗系统或者Qt 本身在各种不同的情况下产生的。当用户点击或者释放鼠标&#xff0c;键盘时&#xff0c;一个鼠标事件或者键盘事件就产生了。当窗口第一次显示时&#xff0c;一个绘制事件会产生告诉新可见的窗口绘…

【Dify 案例】【MCP实战】【三】【超级美食家】

接上次的超级助理,我们这一期给出一个超级美食家 首先:我的MCP要申请一个key ` 我们来看看这个MCP服务怎么使用呢。`https://modelscope.cn/mcp/servers/@worryzyy/howtocook-mcp插件里面需要配置 {"mcpServers":{"amap-amap-sse":{"url":&qu…

4.文件管理(文本、日志、Excel表)

目录 1.文本 2.日志 3.Excel表 1.文本 using System.Text;namespace (自己创建的一个类) {/// <summary>/// 配置文件*.ini读写器。/// </summary>public class IniFile{[System.Runtime.InteropServices.DllImport("kernel32")]private static ex…

Java 包装类详解

什么是包装类 Java包装类&#xff08;Wrapper Classes&#xff09;是将8种基本数据类型封装成对象的类&#xff0c;位于java.lang包中。每个基本数据类型都有对应的包装类&#xff1a; byte → Byteshort → Shortint → Integerlong → Longfloat → Floatdouble → Doublec…

阿里云ACP认证-数据仓库

数据仓库 Kappa架构&#xff1a;将实时和离线代码统一&#xff08;优化lambda架构&#xff09;&#xff0c;但是不好修正数据&#xff0c;开发周期长&#xff0c;成本浪费&#xff0c;对于历史数据的高吞吐量力不从心 原一代数据仓库&#xff1a; 离线&#xff1a;hivemaxcom…

WebRTC(五):TURN协议

TURN&#xff08;Traversal Using Relays around NAT&#xff09;协议是一个网络协议&#xff0c;旨在解决 NAT&#xff08;网络地址转换&#xff09;和防火墙 环境下的 UDP/TCP通信问题。它通常与 STUN 和 ICE 协议一起使用&#xff0c;广泛应用于 WebRTC、SIP 和视频会议等实…

Python 的内置函数 hasattr

Python 内建函数列表 > Python 的内置函数 hasattr Python 的内置函数 hasattr() 用于检查一个对象是否具有指定的属性或方法。该函数的语法为&#xff1a; hasattr(object, name)参数说明&#xff1a; object&#xff1a;要检查的对象&#xff0c;可以是任何 Python 对象…

docker使用技巧之把扩展卷命名变成有意义

背景 之前使用别人的镜像之后&#xff0c;启动docker后发出现了一堆看不懂名称的扩展卷 eg&#xff1a;集群查看 扩展卷查看 这个时候如果有很多集群需要清理扩展卷就很麻烦&#xff0c;不知道是哪个集群的 操作步骤 可以实现的分析&#xff1a;这个扩展卷的信息应该是和…

《博物通书》《博物新编》与满清历史篡改

《博物新编》作为近代西方科技输入中国的首部著作&#xff0c;其问世犹如一颗投入平静湖面的巨石&#xff0c;在 19 世纪中期的中国激起层层涟漪&#xff0c;对中国近代科学发展产生了多维度、深层次的影响。它不仅是知识传播的载体&#xff0c;更是推动中国科学从传统走向近代…

【入门】【例18.1】 睡眠

| 时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 64MB&#xff0c;其他语言 128MB 难度&#xff1a;中等 分数&#xff1a;100 OI排行榜得分&#xff1a;12(0.1分数2难度) 出题人&#xff1a;root | 描述 一个人只有每天睡眠时间到达 8…

DAY 38 Dataset和Dataloader类

知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 作业&#xff1a;了解下cifar数据集&#xff0c;尝试获取其中一张图片 import torch import torch.nn as nn import torch.o…