量子密码的轻量级通信协议笔记
代码笔记
本文档提供了项目代码的详细说明,包括代码结构、关键算法实现和重要的代码片段。
代码结构
.
├── Makefile # 构建系统配置
├── coap_client.c # CoAP客户端实现
├── coap_server.c # CoAP服务端实现
├── coap.c # CoAP协议基础功能实现
├── coap.h # CoAP协议相关定义和函数声明
├── rainbow.c # Rainbow签名算法实现
├── rainbow.h # Rainbow签名相关定义和函数声明
├── protocol_optimize.c # 协议优化算法实现
├── protocol_optimize.h # 协议优化相关定义和函数声明
├── protocol_test.c # 协议优化性能测试
├── performance_analyzer.c # 性能分析工具
├── visualize_performance.py # 性能数据可视化脚本
└── run_tests.sh # 测试脚本
代码规范
项目采用C语言实现,遵循以下规范:
-
命名规范:
- 函数名: 使用小写字母和下划线,如
rainbow_sign()
- 变量名: 使用小写字母和下划线,如
message_id
- 常量和宏: 使用大写字母和下划线,如
KYBER_PUBLICKEYBYTES
- 结构体: 使用驼峰命名法,如
PerformanceMetrics
- 函数名: 使用小写字母和下划线,如
-
代码缩进:
- 使用4个空格缩进
- 大括号放在同一行
-
注释规范:
- 函数前使用多行注释说明功能
- 复杂逻辑处使用单行注释
- 所有公共API都有文档注释
-
错误处理:
- 所有函数返回值都进行检查
- 使用返回值指示错误状态
- 内存分配都检查是否成功
CoAP协议实现 (coap.c/h)
CoAP消息格式
typedef struct {uint8_t version; // CoAP版本号(固定为1)uint8_t type; // 消息类型(CON, NON, ACK, RST)uint8_t token_len; // 令牌长度(0-8字节)uint8_t code; // 响应码uint16_t message_id; // 消息IDuint8_t token[8]; // 令牌Option *options; // 选项链表uint8_t *payload; // 有效负载size_t payload_len; // 有效负载长度
} CoAPMessage;
消息类型
#define COAP_MESSAGE_CON 0 // 需要确认的消息
#define COAP_MESSAGE_NON 1 // 不需要确认的消息
#define COAP_MESSAGE_ACK 2 // 确认消息
#define COAP_MESSAGE_RST 3 // 重置消息
核心函数
消息创建和释放
// 创建新的CoAP消息
CoAPMessage *coap_message_create();// 释放CoAP消息资源
void coap_message_free(CoAPMessage *message);
消息编码和解码
// 将CoAP消息编码为二进制格式
int coap_message_encode(const CoAPMessage *message, uint8_t *buffer, size_t buffer_len);// 从二进制数据解码CoAP消息
int coap_message_decode(CoAPMessage *message, const uint8_t *buffer, size_t buffer_len);
分块传输实现
实现了简化版的CoAP分块传输机制,使用Block2选项:
// 添加Block2选项
int coap_add_block2_option(CoAPMessage *message, uint32_t num, uint8_t more, uint16_t size);// 解析Block2选项
int coap_parse_block2_option(const CoAPMessage *message, uint32_t *num, uint8_t *more, uint16_t *size);
Rainbow签名实现 (rainbow.h/c)
关键数据结构
// Rainbow密钥对结构
typedef struct {unsigned char public_key[RAINBOW_PUBLIC_KEY_BYTES];unsigned char private_key[RAINBOW_PRIVATE_KEY_BYTES];
} RainbowKeyPair;
主要函数
密钥生成
void rainbow_keygen(RainbowKeyPair *keypair) {printf("rainbow_keygen 开始\n");// 使用 rand() 生成私钥for (int i = 0; i < RAINBOW_PRIVATE_KEY_BYTES; i++) {keypair->private_key[i] = rand() % 256;}// 使用 SHA256 哈希私钥生成公钥,确保单向性unsigned char hash[SHA256_DIGEST_LENGTH];SHA256(keypair->private_key, RAINBOW_PRIVATE_KEY_BYTES, hash);for (int i = 0; i < RAINBOW_PUBLIC_KEY_BYTES; i++) {keypair->public_key[i] = hash[i % SHA256_DIGEST_LENGTH];}printf("rainbow_keygen 完成,私钥前16字节: ");for (int i = 0; i < 16; i++) printf("%02x", keypair->private_key[i]);printf("\n公钥前16字节: ");for (int i = 0; i < 16; i++) printf("%02x", keypair->public_key[i]);printf("\n");
}
签名和验证
// 签名实现
void rainbow_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key) {// 计算消息哈希unsigned char hash[SHA256_DIGEST_LENGTH];SHA256(message, message_len, hash);// 生成签名 = 哈希 XOR 私钥for (int i = 0; i < RAINBOW_SIGNATURE_BYTES; i++) {signature[i] = hash[i % SHA256_DIGEST_LENGTH] ^ private_key[i % RAINBOW_PRIVATE_KEY_BYTES];}
}// 简化的验证实现(实际使用中替换为真正的验证逻辑)
int rainbow_verify(const unsigned char *message, size_t message_len, const unsigned char *signature, const unsigned char *public_key) {// 注意:这是一个简化实现,总是返回验证成功return 1;
}
协议优化实现 (protocol_optimize.c/h)
1. 报文压缩 (RLE算法)
// 应用游程长度编码(RLE)压缩
size_t apply_compression(unsigned char *input, size_t input_len, unsigned char *output, size_t output_max_len) {// 如果输入数据较小,直接使用未压缩模式if (input_len < 512) {output[0] = 0xC1; // 未压缩标记memcpy(output + 1, input, input_len);return input_len + 1;}size_t out_pos = 1; // 保留第一个字节作为压缩模式标记size_t in_pos = 0;while (in_pos < input_len) {// 查找连续相同的字节序列unsigned char current = input[in_pos];size_t run_length = 1;while (in_pos + run_length < input_len && input[in_pos + run_length] == current && run_length < 255) {run_length++;}// 如果序列长度超过3,使用RLE编码if (run_length >= 3) {// 写入RLE标记、重复字节和重复次数output[out_pos++] = 0xFF; // RLE标记output[out_pos++] = current; // 重复字节output[out_pos++] = run_length; // 重复次数} else {// 对于短序列,直接复制for (size_t j = 0; j < run_length; j++) {output[out_pos++] = current;}}// 移动到下一个未处理的字节in_pos += run_length;}// 设置压缩模式标记output[0] = 0xC0;return out_pos;
}
解压缩实现
// 对应的解压缩算法
size_t decompress_data(unsigned char *input, size_t input_len, unsigned char *output, size_t output_max_len) {// 检查压缩标记if (input[0] == 0xC1) {// 未压缩数据,直接复制size_t copy_len = input_len - 1;if (copy_len > output_max_len) {copy_len = output_max_len;}memcpy(output, input + 1, copy_len);return copy_len;} else if (input[0] != 0xC0) {// 无效的压缩标记return 0;}// 解压缩RLE编码的数据size_t in_pos = 1; // 跳过压缩标记size_t out_pos = 0;while (in_pos < input_len && out_pos < output_max_len) {// 检查是否是RLE编码标记if (input[in_pos] == 0xFF && in_pos + 2 < input_len) {// 读取重复字节和次数unsigned char value = input[in_pos + 1];unsigned char count = input[in_pos + 2];// 展开重复序列for (unsigned char i = 0; i < count; i++) {output[out_pos++] = value;}// 移动到下一个编码in_pos += 3;} else {// 直接复制单个字节output[out_pos++] = input[in_pos++];}}return out_pos;
}
2. 会话密钥复用
数据结构
// 会话密钥缓存结构
typedef struct {unsigned char key[64]; // 足够大以存储各种密钥size_t key_len;unsigned char associated_data[256]; // 关联数据(如IP地址、端口等)size_t ad_len;time_t creation_time;int valid;
} SessionKeyCache;#define MAX_SESSION_KEYS 10
static SessionKeyCache session_keys[MAX_SESSION_KEYS];
static int session_key_count = 0;
密钥保存与检索
// 保存会话密钥供后续使用
void save_session_key(const unsigned char *key, size_t key_len, const unsigned char *associated_data, size_t ad_len) {int index = -1;// 如果已存在相同关联数据的条目,则更新它if (associated_data && ad_len > 0) {for (int i = 0; i < session_key_count; i++) {if (session_keys[i].ad_len == ad_len && memcmp(session_keys[i].associated_data, associated_data, ad_len) == 0) {index = i;break;}}}// 如果未找到现有条目,创建一个新的或替换最老的if (index == -1) {if (session_key_count < MAX_SESSION_KEYS) {index = session_key_count++;} else {// 替换最老的会话密钥time_t oldest_time = time(NULL);int oldest_idx = 0;for (int i = 0; i < MAX_SESSION_KEYS; i++) {if (session_keys[i].creation_time < oldest_time) {oldest_time = session_keys[i].creation_time;oldest_idx = i;}}index = oldest_idx;}}// 更新会话密钥条目memcpy(session_keys[index].key, key, key_len);session_keys[index].key_len = key_len;if (associated_data && ad_len > 0) {memcpy(session_keys[index].associated_data, associated_data, ad_len);session_keys[index].ad_len = ad_len;}session_keys[index].creation_time = time(NULL);session_keys[index].valid = 1;
}// 检索之前保存的会话密钥
int retrieve_session_key(unsigned char *key, size_t key_len,const unsigned char *associated_data, size_t ad_len) {for (int i = 0; i < session_key_count; i++) {if (session_keys[i].valid && session_keys[i].ad_len == ad_len && memcmp(session_keys[i].associated_data, associated_data, ad_len) == 0) {// 检查密钥是否过期 (24小时)time_t now = time(NULL);if (now - session_keys[i].creation_time > 24 * 60 * 60) {session_keys[i].valid = 0;return 0;}// 复制密钥size_t copy_len = key_len < session_keys[i].key_len ? key_len : session_keys[i].key_len;memcpy(key, session_keys[i].key, copy_len);return 1; // 成功找到并复制密钥}}return 0; // 未找到匹配的密钥
}
3. 协议头压缩
// 应用协议头压缩
size_t apply_header_reduction(unsigned char *buffer, size_t buffer_len) {// 添加协议头压缩标记 0xA5unsigned char header_flag = 0xA5;// 检查是否是CoAP首包并需要压缩if (buffer_len >= 8 && ((buffer[0] >> 4) & 0x0F) <= 3) {// 提取和保留重要字段unsigned char type_ver = buffer[0];unsigned char code = buffer[1];unsigned short message_id = (buffer[2] << 8) | buffer[3];// 创建压缩头部unsigned char new_header[5];new_header[0] = header_flag;new_header[1] = type_ver;new_header[2] = code;new_header[3] = (message_id >> 8) & 0xFF;new_header[4] = message_id & 0xFF;// 计算选项部分起始位置size_t options_start = 4;size_t payload_marker_pos = 0;// 找到有效载荷标记0xFF的位置for (size_t i = options_start; i < buffer_len; i++) {if (buffer[i] == 0xFF) {payload_marker_pos = i;break;}}// 如果找到有效载荷标记if (payload_marker_pos > 0) {// 计算需要移动的数据大小size_t options_size = payload_marker_pos - options_start;size_t payload_size = buffer_len - payload_marker_pos - 1;// 复制压缩头部memmove(buffer, new_header, 5);// 复制选项部分(如果有)if (options_size > 0) {memmove(buffer + 5, buffer + options_start, options_size);}// 添加有效载荷标记buffer[5 + options_size] = 0xFF;// 复制有效载荷数据(如果有)if (payload_size > 0) {memmove(buffer + 5 + options_size + 1, buffer + payload_marker_pos + 1, payload_size);}// 返回新的缓冲区长度return 5 + options_size + 1 + payload_size;}}// 如果不能压缩,返回原始长度return buffer_len;
}
性能测试 (protocol_test.c)
测试数据生成
// 生成测试数据
TestData generate_test_data(size_t size) {TestData data;data.data = (unsigned char *)malloc(size);data.data_len = size;if (data.data) {// 填充一些模拟数据for (size_t i = 0; i < size; i++) {// 生成一些模式用于测试压缩效果if (i % 100 < 20) {data.data[i] = 0x00; // 一些零字节} else if (i % 100 < 40) {data.data[i] = 0xFF; // 一些FF字节} else if (i % 100 < 60) {data.data[i] = i & 0xFF; // 递增模式} else if (i % 100 < 80) {data.data[i] = 'A' + (i % 26); // 文本模式} else {data.data[i] = rand() & 0xFF; // 随机数据}}}return data;
}
性能计时器
// 启动计时器
void start_timer(struct timespec *timer) {if (!timer) return;clock_gettime(CLOCK_MONOTONIC, timer);
}// 停止计时器并返回经过的毫秒数
double stop_timer(struct timespec *timer) {if (!timer) return 0.0;struct timespec end;clock_gettime(CLOCK_MONOTONIC, &end);double milliseconds = (end.tv_sec - timer->tv_sec) * 1000.0;milliseconds += (end.tv_nsec - timer->tv_nsec) / 1000000.0;return milliseconds;
}
客户端和服务端实现
客户端通信流程
// 简化的客户端通信逻辑
int main() {// 1. 初始化(创建套接字、绑定端口等)int sock = socket(AF_INET, SOCK_DGRAM, 0);// 2. 生成密钥对(Kyber和Rainbow)crypto_kem_keypair(client_pk, client_sk);rainbow_keygen(&rainbow_keypair);// 3. 发送公钥到服务端CoAPMessage *request = coap_message_create();// ... 设置请求参数coap_send_request(sock, request, server_addr);// 4. 接收服务端的公钥和密文CoAPMessage *response = coap_receive_response(sock);// 5. 解密共享密钥crypto_kem_dec(shared_secret, server_ciphertext, client_sk);// 6. 验证服务端签名rainbow_verify(server_message, message_len, server_signature, server_rainbow_pk);// 7. 使用共享密钥进行后续通信// ...return 0;
}
服务端通信流程
// 简化的服务端通信逻辑
int main() {// 1. 初始化(创建套接字、绑定端口等)int sock = socket(AF_INET, SOCK_DGRAM, 0);bind(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));// 2. 生成密钥对(Kyber和Rainbow)crypto_kem_keypair(server_pk, server_sk);rainbow_keygen(&rainbow_keypair);// 3. 等待客户端连接并接收公钥CoAPMessage *request = coap_receive_request(sock);// 4. 使用客户端公钥加密共享密钥crypto_kem_enc(ciphertext, shared_secret, client_pk);// 5. 对消息进行签名rainbow_sign(signature, message, message_len, rainbow_keypair.private_key);// 6. 发送服务端公钥、密文和签名CoAPMessage *response = coap_message_create();// ... 设置响应参数coap_send_response(sock, response, client_addr);// 7. 使用共享密钥进行后续通信// ...return 0;
}
优化算法复杂度分析
1. 报文压缩算法 (RLE)
- 时间复杂度: O(n),其中n是输入数据的长度
- 空间复杂度: O(n),最坏情况下压缩后数据与原始数据大小相当
- 最佳场景: 数据中包含大量连续重复字节
2. 会话密钥复用
- 时间复杂度:
- 保存: O(k),其中k是最大存储的密钥数量
- 检索: O(k),需要线性搜索所有密钥
- 空间复杂度: O(k),存储k个密钥及其元数据
- 优化点: 可以使用哈希表提高检索效率至O(1)
3. 协议头压缩
- 时间复杂度: O(n),其中n是消息长度
- 空间复杂度: O(1),使用固定额外空间
- 节省空间: 通常在小数据包中节省1-5字节
安全考虑
密钥管理
- 当前实现中,密钥直接存储在内存中,生产环境应考虑:
- 安全的密钥存储(如TPM, HSM)
- 密钥分发机制
- 密钥轮换策略
简化实现的限制
- Rainbow签名实现是简化版本,不提供真正的安全保证
- 会话密钥目前只有简单的时间失效机制
- 没有防止重放攻击的机制
增强安全性的建议
- 替换Rainbow为标准化的后量子签名算法
- 添加随机数和时间戳防止重放攻击
- 实现完整的TLS/DTLS安全层
- 加入密钥衍生函数(KDF)和安全的随机数生成器
调试技巧
输出调试信息
在关键函数中添加如下代码以启用调试输出:
#ifdef DEBUG_LOGGING
#define DEBUG_LOG(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__)
#else
#define DEBUG_LOG(fmt, ...)
#endif// 使用示例
DEBUG_LOG("Processing message ID: %d", message_id);
内存调试
使用Valgrind检查内存泄漏:
valgrind --leak-check=full --show-leak-kinds=all ./coap_server
网络调试
使用tcpdump或Wireshark捕获CoAP数据包:
sudo tcpdump -i lo udp port 5683 -vvv -X
相关文章:
量子密码的轻量级通信协议笔记
代码笔记 本文档提供了项目代码的详细说明,包括代码结构、关键算法实现和重要的代码片段。 代码结构 . ├── Makefile # 构建系统配置 ├── coap_client.c # CoAP客户端实现 ├── coap_server.c # CoAP服务端实现 ├─…...
探索 C++ 在行业应用与技术融合中的核心价值
引言 在科技飞速发展的今天,C 作为一门兼具高性能与灵活性的编程语言,正深度融入游戏开发、人工智能、区块链等多个关键领域。其高效的内存管理、底层控制能力以及对现代硬件架构的深度优化,使其成为复杂系统开发的首选语言。本文将深入探讨…...
雷赛伺服电机
ACM0经济 编码器17位: ACM1基本 编码器23位磁编, ACM2通用 编码器24位光电, 插头定义:...
word文档基本操作: 编辑页眉页脚和插入目录
文章目录 引言I 编辑页眉页脚II 插入目录III 知识扩展基于axure画架构图基于Knife4j导出接口文档基于PDManer导出数据库设计文档引言 背景: 信息安全认证需要准备相关文件用于审核 一般的开发设计包含总体设计、概要设计、详细设计、接口设计、数据库设计、部署结构设计、原型…...
数据结构(二)——线性表的链式表示和实现
一、单链表 1.单链表的定义 如图所示每个节点包含两个域:数据域和指针域。数据域存储数据元素,指针域存储下一个节点的地址,因此指针指向的类型也是节点类型。每个指针都指向下一个节点,都是朝一个方向的,这样的链表称为单向链表…...
HTML10:iframe内联框架
iframe内部框架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>内联框架学习</title> </head> <body> <!--iframe内联框架 src:地址 width-height:高度宽度 --> <iframe…...
C++代码随想录刷题知识分享-----数组交集—LeetCode 349
1 题目描述 给定两个整型数组 nums1 和 nums2,请返回它们的交集。 交集中 每个元素必须是唯一的。输出结果的顺序可以任意。 示例输入输出说明1nums1 [1,2,2,1], nums2 [2,2][2]2 只出现一次2nums1 [4,9,5], nums2 [9,4,9,8,4][4,9] 或 [9,4]顺序不作要求…...
Wireshark基本使用
本文会对Wireshark做简单介绍,带大家熟悉一下Wireshark的界面,以及如何使用过滤器。 接着会带大家查看TCP五层模型下,带大家回顾各层首部的格式。 最后会演示 Wireshark 如何抓取三次握手和四次挥手包的过程。 目录 一.Wireshark简介 二…...
学习c语言的链表的概念、操作(另一篇链表的笔记在其他的栏目先看这个)
在学习Linux之间我们先插入一下链表的知识 学习链表(一种数据结构思想) 链表和数组的区别和实现: 链表(链表是个好东西) 链表概念(什么是链表)? 链表就是数据结构->数据的存储…...
快速上手Pytorch Lighting框架 | 深度学习入门
快速上手Pytorch Lighting框架 | 深度学习入门 前言参考官方文档 介绍快速上手基本流程常用接口LightningModule\_\_init\_\_ & setup()\*\_step()configure_callbacks()configure_optimizers()load_from_checkpoint Trainer常用参数 可选接口LoggersTensorBoard Logger Ca…...
ffmpeg多媒体(音视频)处理常用命令
概览 总结一些音视频常用的ffmpeg处理命令,会不断更新,涉及一些重要命令,各位读者也可在评论区不断更新,维护起来,希望可以帮助大家快速解决问题! 1、音频相关 1.1 音频信息查看 ffmpeg -i test.wav 该命…...
QT中的网络请求
一、主程序(main.cpp) #include <QCoreApplication> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> #include <QUrlQuery> #include <QJsonDocument> #include <QJso…...
Nacos源码—6.Nacos升级gRPC分析二
大纲 1.Nacos 2.x版本的一些变化 2.客户端升级gRPC发起服务注册 3.服务端进行服务注册时的处理 4.客户端服务发现和服务端处理服务订阅的源码分析 4.客户端服务发现和服务端处理服务订阅的源码分析 (1)Nacos客户端进行服务发现的源码 (2)Nacos服务端处理服务订阅请求的源…...
如何选择自己喜欢的cms
选择内容管理系统cms what is cms1.whatcms.org2.IsItWP.com4.Wappalyzer5.https://builtwith.com/6.https://w3techs.com/7. https://www.netcraft.com/8.onewebtool.com如何在不使用 CMS 检测器的情况下手动检测 CMS 结论 在开始构建自己的数字足迹之前,大多数人会…...
前端面经 作用域和作用域链
含义:JS中变量生效的区域 分类:全局作用域 或者 局部作用域 局部作用域:函数作用域 和 块级作用域ES6 全局作用域:在代码中任何地方都生效 函数中定义函数中生效,函数结束失效 块级作用域 使用let或const 声明 作用域链:JS查…...
开启智能Kubernetes管理新时代:kubectl-ai让操作更简单!
在如今的科技世界中,Kubernetes 已经成为容器编排领域的标杆,几乎所有现代应用的基础设施都离不开它。然而,面对复杂的集群管理和日常运维,许多开发者常常感到无所适从。今天,我们将为大家介绍一款结合了人工智能的强大工具——kubectl-ai。它不仅能帮助开发者更加顺畅地与…...
STM32 ADC
目录 ADC简介 逐次逼近型ADC STM32 ADC框图 输入通道 转换模式 •单次转换,非扫描模式 •连续转换,非扫描模式 •单次转换,扫描模式 •连续转换,扫描模式 触发控制 数据对齐 转换时间 校准 硬件电路 A…...
nextjs站点地图sitemap添加
app/sitemap.xml/route.ts (主站点地图索引) sitemap.xml 为文件夹名称 route.ts代码如下: import { NextResponse } from next/server; import { url } from /config/navigation; export async function GET() {// const entries generateMonthlyEntries();con…...
TCP/IP和OSI对比
TCP/IP模型的实际特性 网络层(IP层) 仅提供无连接的不可靠服务:TCP/IP模型的网络层核心协议是IP(Internet Protocol),其设计是无连接且不可靠的。IP数据包独立传输,不保证顺序、不确认交…...
【hadoop】Hbase java api 案例
代码实现: HBaseConnection.java package com.peizheng.bigdata;import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client…...
深入理解Spring缓存注解:@Cacheable与@CacheEvict
在现代应用程序开发中,缓存是提升系统性能的重要手段。Spring框架提供了一套简洁而强大的缓存抽象,其中Cacheable和CacheEvict是两个最常用的注解。本文将深入探讨这两个注解的工作原理、使用场景以及最佳实践。 1. Cacheable注解 基本概念 Cacheable…...
[git]如何关联本地分支和远程分支
主题 本文总结如何关联git本地分支和远程分支的相关知识点。 详情 查看本地分支 git branch 查看远程分支 git branch -r 查看所有分支(本地远程) git branch -a 查看本地分支及其关联的远程分支(如有) git branch -vv 关联本地分支到远程分支: git branch …...
Linux58 ssh服务配置 jumpserver 测试双网卡 为何不能ping通ip地址
判断为NAT模式网卡 能ping 通外网 ens34为仅主机模式网卡 [rootlocalhost network-scripts]# ip route show default default via 10.1.1.254 dev ens33 proto static metric 100 10.0.0.0/8 dev ens33 proto kernel scope link src 10.1.1.37 metric 100 11.0.0.0/8 dev…...
chart.js 柱状图Y轴数据设置起始值
事情的起因, 我以为是: chart.js 柱状图Y轴数据显示不全, 因为数据是浮点数, 换了整数测试还不行, 多次更换数据, 数据显示不全仍然存在, 而且是不固定位置的不显示。 直到相同数据换了折…...
算法题(142):木材加工
审题: 本题需要我们找到可以将木头切割至少k段的单段长度最长值 思路: 方法一:暴力解法 首先我们知道单段长度的最长值就是数组中数据的最大值max,所以我们可以遍历1~max的数据,将他们确定为l,然后计算出当…...
嵌入式学习--江协51单片机day3
今天学的东西挺多的,包括:自己设计的小应用,矩阵键盘,矩阵键盘密码锁,控制按键led流水灯,定时器时钟 (那个视频真的煎熬,连续两个1小时的简直要命,那个时钟也是听的似懂…...
Linux命令行参数注入详解
本文主要聚焦 Linux 系统及其 ELF 二进制文件,深入探讨参数注入的原理与防范措施。 核心术语解析 在进入主题之前,我们先厘清几个关键术语,以确保理解的准确性: 参数解析器 当程序被调用时,操作系统会向程序的 main…...
【HCIP】----OSPF综合实验
实验题目 实验需求: 1,R5为ISP,其上只能配置IP地址;R4作为企业边界路由器, 出口公网地址需要通过PPP协议获取,并进行chap认证 2,整个OSPF环境IP基于172.16.0.0/16划分; 3࿰…...
C++模板笔记
Cpp模板笔记 文章目录 Cpp模板笔记1. 为什么要定义模板2. 模板的定义2.1 函数模板2.1.1 函数模板的重载2.1.2 头文件与实现文件形式(重要)2.1.3 模板的特化2.1.4 模板的参数类型2.1.5 成员函数模板2.1.6 使用模板的规则 2.2 类模板2.3 可变参数模板 模板…...
二极管的动态特性
主要内容 二极管的单向导电特性并不十分理想,这是因为二极管的本质是有P型半导体和N型半导体接触形成的PN结。 PN结除了除了构成单向到点的二极管外,还存在一个结电容,这个结电容会导致"双向"导电。 也就是说,这会让二…...
WSL(Windows Subsystem for Linux)入门
目录 1.简介2.安装与配置3.常用命令4.进阶使用4.1 文件系统交互4.2 网络互通4.3 配置代理4.4 运行 GUI 程序4.5 Docker 集成 1.简介 WSL 是 Windows 系统内置的 Linux 兼容层,允许直接在 Windows 中运行 Linux 命令行工具和应用程序,无需虚拟机或双系统…...
k8s术语之secret
在kubernetes中,还存在一种和ConfigMap非常类似的对象,称之为Secret对象。它主要用于存储敏感信息,例如密码、密钥、证书等等。 首先使用base64对数据进行编码 rootmaster pvs ]# echo -n admin | base64 YWRtaW4 实例:隐藏mysql密…...
Vue2 中 el-dialog 封装组件属性不生效的深度解析(附 $attrs、inheritAttrs 原理)
Vue2 中 el-dialog 封装组件属性不生效的深度解析(附 $attrs、inheritAttrs 原理) 在使用 Vue2 和 Element UI 进行组件封装时,我们常会遇到父组件传入的属性不生效的情况,比如在封装的 el-dialog 组件中传入 width"100%&qu…...
使用Compose编排工具搭建Ghost博客系统
序:需要提前自备一台部署好docker环境的虚拟机,了解并熟练compose编排工具 在Centos7中,在线/离线安装Docker:https://blog.csdn.net/2301_82085712/article/details/147140694 Docker编排工具---Compose的概述及使用࿱…...
车载网络TOP20核心概念科普
一、基础协议与总线技术 CAN总线 定义:控制器局域网,采用差分信号传输,速率最高1Mbps,适用于实时控制(如动力系统)。形象比喻:如同“神经系统”,负责传递关键控制信号。 LIN总线 定…...
机器学习第一讲:机器学习本质:让机器通过数据自动寻找规律
机器学习第一讲:机器学习本质:让机器通过数据自动寻找规律 资料取自《零基础学机器学习》。 查看总目录:学习大纲 一、从婴儿学说话说起 👶 想象你教1岁宝宝认「狗」: 第一阶段:指着不同形态的狗&#x…...
Android ImageView 加载 Base64编码图片
在 Android 中显示服务端返回的 Base64 编码的 GIF 图片(如 data:image/gif;base64,...),需要以下步骤: 首先从字符串中分离出纯 Base64 部分(去掉 data:image/gif;base64, 前缀)image/gif 表示图片是 gif…...
如何使用 QuickAPI 推动医院数据共享 —— 基于数据仓库场景的实践
目录 01 医疗行业面临的数据孤岛问题 02 QuickAPI:将 SQL 变为数据 API 的利器 03 快速落地的应用实践 ✅ 步骤一:统一 SQL 逻辑,模块化管理 ✅ 步骤二:配置权限与调用策略 ✅ 步骤三:上线并接入调用 04 核心收…...
【5G通信】bwp和redcap 随手记 2
好的,让我们重新解释Cell-Defined BWP (CD BWP) 和 Non-Cell-Defined BWP (NCD BWP),并结合RedCap终端和非RedCap终端的应用进行说明。 一、定义 Cell-Defined BWP (CD BWP) 定义:由网络(基站)通过RRC信令为终端配置的…...
AI时代企业应用系统架构的新思路与CIO变革指南
作为制造企业CIO,我们看问题需要有前瞻性,AI时代企业应用系统架构需要进行全面转型。 一、新思想与新技术 1. 核心新思想 可视化开发AI的融合模式:不再只依赖纯代码开发或传统低代码,而是两者结合,通过AI理解自然语…...
kotlin JvmName注解的作用和用途
1. JvmName 注解的作用 JvmName 是 Kotlin 提供的一个注解,用于在编译为 Java 字节码时自定义生成的类名或方法名。 作用对象: 文件级别(整个 .kt 文件)函数、属性、类等成员 主要用途: 控制 Kotlin 编译后生成的 JV…...
为什么强调 RESTful 的无状态性?-优雅草卓伊凡
为什么强调 RESTful 的无状态性?-优雅草卓伊凡 RESTful 架构的核心原则之一是 无状态性(Statelessness),它要求 每次客户端请求必须包含服务器处理该请求所需的所有信息,服务器不会存储客户端的状态(如会话…...
信息系统项目管理工程师备考计算类真题讲解十五
一、决策论问题 分析:首先要明白几个概念: 1)最大最大准则(Maxmax):也称乐观主义准则,其决策原则为“大中取大” 2)最大最小准则(Maxmin):也称悲观主义准则,…...
android-ndk开发(9): undefined reference to `__aarch64_ldadd4_acq_rel` 报错分析
1. 概要 基础库 libbase.a 基于 android ndk r18b 编译, 被算法库 libfoo.so 和算法库 libbar.a 依赖, 算法库则分别被 libapp1.so 和 libapp2.so 依赖。 libapp1.so 的开发者向 libfoo.so 的开发者反馈了链接报错: error: undefined symb…...
Java 对象克隆(Object Cloning)详解
Java 对象克隆(Object Cloning)详解 对象克隆是指创建一个对象的精确副本,Java 提供了两种克隆方式:浅克隆(Shallow Clone)和深克隆(Deep Clone)。下面从实现原理、使用场景到注意事项全面解析。 一、克隆的基本概念 1. 为什么要克隆? 需要对象副本时避免修改原始对…...
Asp.Net Core IIS发布后PUT、DELETE请求错误405
一、方案1 1、IIS管理器,处理程序映射。 2、找到aspNetCore,双击。点击请求限制...按钮,并在谓词选项卡上,添加两者DELETE和PUT. 二、方案2 打开web.config文件,添加<remove name"WebDAVModule" />&…...
AI搜索的未来:技术纵深发展与关键突破路径
一、模型架构的颠覆性重构 1、混合专家系统(MoE)的工程化突破 动态路径选择:Google Gemini 1.5 Pro采用MoE架构,其门控网络(Gating Network)通过实时计算输入token与128个专家模型的余弦相似度,动态分配计算资…...
从艾米・阿尔文看 CTO 的多面特质与成长路径
在《对话 CTO,驾驭高科技浪潮》的开篇,艾米・阿尔文的经历如同一扇窗,为我们展现出首席技术官丰富而立体的世界。通过深入探究这一章节,我们能洞察 CTO 在技术领域前行所需的特质、面临的挑战,以及成长发展的脉络。 一…...
记录阿里云服务器搭建FTP服务器的注意事项
在阿里云服务器上(centos)系统,使用vsftpd搭建了一台FTP服务器。 搭建过程中,也留意到了操作防火墙放行端口。但搭建成功后,仍无法访问。 问题是:还需要在阿里云控制台设置一下。 在此记录。 1、登陆账…...
第二章 Logback的架构(三)
Logger, Appenders 和 Layouts 工作原理概述 在介绍了基本的Logback组件之后,我们现在可以描述当用户调用Logger的打印方法时,Logback框架日志请求的执行步骤。 现在让我们分析一下当用户调用名为com.wombat的Logger的info()方法时,Logback…...