STM32在Keil5中利用Jansson库处理和组装JSON数据【详细版】

news2024/12/28 23:35:26

在Keil5中利用Jansson库处理和组装JSON数据


下载Keil.Jansson.1.0.0.pack

https://keilpack.azureedge.net/pack/Keil.Jansson.1.0.0.packicon-default.png?t=O83Ahttps://keilpack.azureedge.net/pack/Keil.Jansson.1.0.0.pack
下载完成后直接安装到keil5中即可

选择Jansson库的理由:轻量、易用、适配嵌入式

Jansson库之所以被选用,主要基于以下三大核心优势:

  • 轻量级:Jansson库设计紧凑,占用资源少,非常适合资源受限的嵌入式环境。
  • 易用性:提供简洁直观的API,使得JSON数据的解析与组装变得简单快捷。
  • 嵌入式适配:特别注重在嵌入式系统中的应用,支持多种平台,优化性能以减少资源消耗。

这些特点使得Jansson库成为嵌入式系统中处理JSON数据的优选工具。

配置Jansson

①:打开keil5后,点击工具栏中魔术棒右边具有四个黑点的绿色正方形

②:点击Data Exchange: 里面可以看到安装的拓展库,例如这里显示JSON,

                这里将下方的Jansson勾选

如果keil5左边项目文件中包含了这个图像和相关的jansson文件代表Jansson环境配置成功

配置printf
 

如果需要使用printf的话,这里放一个传送门

或者也可以直接使用串口发送函数

STM32基于HAL库串口printf使用和接收icon-default.png?t=O83Ahttps://blog.csdn.net/Wang2869902214/article/details/141719519

这里无论是不是HAL库,都可以按照上方文章说明配置,
只需在重定向代码中更换对应的串口发送函数

解析json格式数据代码

这里使用STM32F103C8T6芯片作为测试硬件,软件方面需要准备一个串口调试助手,用来查看代码运行时的状态

文章中的代码只是用来举一反三,可以根据它的编程规律和函数命名规律,可以合理的推断出解析整形还是字符串还是浮点数的转换函数
 

这里注意一点:
如果Json解析代码是正确的,然后解析的内容与预期不符,很可能是程序中设置的堆大小不足,
解决方法:在启动文件中:startup_stm32f103xb.s中找到

Heap_Size      EQU     0x200

修改为(也可以在STM32CubeMX软件代码生成时修改)

Heap_Size      EQU     0x800

这里使用简单的字符串先模拟一下解析json格式的数据,提取里面每个Json对象的数据

创建了一个字符串:

const char *json_str = "{\"name\":\"Huan\",\"age\":19,\"city\":\"Mei Zhou\"}";

目的:提取出这些"name","age","city"字段的数据

完整代码1

#include "main.h"
#include <stdio.h>  
#include "jansson.h"  

const char *json_str = "{\"name\":\"Huan\",\"age\":19,\"city\":\"Mei Zhou\"}";

typedef struct
{
	char name[10];
	uint8_t age;
	char city[10];
}Student_TypeDef;



uint8_t myJsonTest(const char *jsonString, Student_TypeDef *student)
{
    // 解析JSON字符串  
    json_t *root;  
    json_error_t error;  
  
    root = json_loads(jsonString, 0, &error);  
    if (!root) {  
        fprintf(stderr, "Error parsing JSON: %s\r\n", error.text);  
        return 1;  
    }  
  
    // 检查JSON对象是否为有效对象  
    if (!json_is_object(root)) {  
        fprintf(stderr, "Error: JSON is not an object\r\n");  
        json_decref(root);  
        return 1;  
    }  
  
    // 提取并打印name字段  
    json_t *name_value = json_object_get(root, "name");  
    if (json_is_string(name_value)) {  
		strcpy(student->name, json_string_value(name_value));
    } else {  
        printf("Name field is not a string\r\n");  
    }  
  
    // 提取并打印age字段  
    json_t *age_value = json_object_get(root, "age");  
    if (json_is_integer(age_value)) {  
		student->age = json_integer_value(age_value);
    } else {  
        printf("Age field is not an integer\r\n");  
    }  
  
    // 提取并打印city字段  
    json_t *city_value = json_object_get(root, "city");  
    if (json_is_string(city_value)) {  
		strcpy(student->city, json_string_value(city_value)); 
    } else {  
        printf("City field is not a string\r\n");  
    }  
  
    // 释放JSON对象  
    json_decref(root);  
  
    return 0;  
}

int main(void)
{
 
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
	

  while (1)
  {
	Student_TypeDef student = {{0}, 0, {0}};
	printf("\r\n%s\r\n",json_str);
	myJsonTest(json_str, &student);
	printf("name:%s\r\n",student.name);
	printf("age:%d\r\n",student.age);
	printf("city:%s\r\n",student.city);
	HAL_Delay(5000);  
  }
}

代码1运行效果

其他的数据类型转换方法就举一反三即可

这里注意一点:
如果Json解析代码是正确的,然后解析的内容与预期不符,很可能是程序中设置的堆大小不足,
解决方法:在启动文件中:startup_stm32f103xb.s中找到

Heap_Size      EQU     0x200

修改为(也可以在STM32CubeMX软件代码生成时修改)

Heap_Size      EQU     0x800


注意事项:上文提到加堆设置,是因为这里json初始化使用的是动态分配空间(malloc),如果堆设置范围太小,那么这里json解析时分配不了所需要的空间,会导致解析失败,包括后面要提到的组装json

json_loads(jsonString, 0, &error);  //内部处理:动态开辟空间

既然是需要动态分配空间,那么在使用结束后也是需要释放空间的,否则运行几次程序就会异常

 json_decref(root);  //内部处理:释放空间

也正是因为这个代码的使用他需要开辟和释放空间,就说明在这个内存的生命周期结束后,里面所有的返回字符串指针全部会被清空,涉及到字符串的情况下,需要使用拷贝函数,将字符串拷贝到自己生命周期更长的变量中,例如上方的Student_TypeDef结构体

如果需要解析一个多重json对象,例如下方代码

const char *json_str = "{\"id\": \"123\",\"params\":{\"name\":{\"value\":\"Huan\"},\"age\":{\"value\":19},\"city\":{\"value\":\"Mei Zhou\"}}}"; 

//原型如下:
{  
  "id": "123",  
  "params": {  
    "name": {  
      "value": "Huan"  
    },  
    "age": {  
      "value": 19  
    },  
    "city": {  
      "value": "Mei Zhou"  
    }  
  }  
}

完整代码2

#include "main.h"
#include <stdio.h>  
#include "jansson.h"  

const char *json_str = "{\"id\": \"123\",\"params\":{\"name\":{\"value\":\"Huan\"},\"age\":{\"value\":19},\"city\":{\"value\":\"Mei Zhou\"}}}"; 
typedef struct
{
	char city[10];
	char name[10];
	char id[10];
	uint8_t age;
	
}Student_TypeDef;



uint8_t myJsonTest(const char *jsonString, Student_TypeDef *student)
{
json_t *root;  
    json_error_t error;  
  
    root = json_loads(jsonString, 0, &error);  
    if (!root) {  
        fprintf(stderr, "Error parsing JSON: %s\r\n", error.text);  
        return 1;  
    }  
  
    if (!json_is_object(root)) {  
        fprintf(stderr, "Error: JSON is not an object\r\n");  
        json_decref(root);  
        return 1;  
    }  
  
	// 提取id的值  
    json_t *id_value = json_object_get(root, "id");  
    if (json_is_string(id_value)) {  
		//id = (char *)json_string_value(id_value);
		strcpy(student->id, (char *)json_string_value(id_value));
    } else {  
        printf("id is not a string\r\n");  
    } 
	
    json_t *params = json_object_get(root, "params");  
    if (json_is_object(params)) {  
        // 提取并打印name字段  
        json_t *name_obj = json_object_get(params, "name");  
        if (json_is_object(name_obj)) {  
            json_t *name_value = json_object_get(name_obj, "value");  
            if (json_is_string(name_value)) {  
                strncpy(student->name, json_string_value(name_value), sizeof(student->name) - 1);  
            } else {  
                printf("Name value is not a string\r\n");  
            }  
        } else {  
            printf("Name field is not an object\r\n");  
        }  
  
        // 提取并打印age字段  
        json_t *age_obj = json_object_get(params, "age");  
        if (json_is_object(age_obj)) {  
            json_t *age_value = json_object_get(age_obj, "value");  
            if (json_is_integer(age_value)) {  
                student->age = (uint8_t)json_integer_value(age_value);  
            } else {  
                printf("Age value is not an integer\r\n");  
            }  
        } else {  
            printf("Age field is not an object\r\n");  
        }  
  
        // 提取并打印city字段  
        json_t *city_obj = json_object_get(params, "city");  
        if (json_is_object(city_obj)) {  
            json_t *city_value = json_object_get(city_obj, "value");  
            if (json_is_string(city_value)) {  
                strncpy(student->city, json_string_value(city_value), sizeof(student->city) - 1);  
            } else {  
                printf("City value is not a string\r\n");  
            }  
        } else {  
            printf("City field is not an object\r\n");  
        }  
    } else {  
        printf("Params field is not an object\r\n");  
    }  
  
    json_decref(root);  
    return 0;   
}

int main(void)
{
 
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
	
	printf("Hello World!\r\n");

  while (1)
  {
	Student_TypeDef student = {{0}, {0}, {0}, 0};
	myJsonTest(json_str, &student);
	printf("id:%s\r\n",student.id);
	printf("name:%s\r\n",student.name);
	printf("age:%d\r\n",student.age);
	printf("city:%s\r\n",student.city);
	HAL_Delay(5000);  
  }
}

代码2运行效果:

 

 这里注意一点:
如果Json解析代码是正确的,然后解析的内容与预期不符,很可能是程序中设置的堆大小不足,
解决方法:在启动文件中:startup_stm32f103xb.s中找到

Heap_Size      EQU     0x200

修改为(也可以在STM32CubeMX软件代码生成时修改)

Heap_Size      EQU     0x800

组装json格式数据代码

 这里注意一点:
如果Json组装代码是正确的,然后组装的内容与预期不符(可能时乱码也可能是空),很可能是程序中设置的堆大小不足,
解决方法:在启动文件中:startup_stm32f103xb.s中找到

Heap_Size      EQU     0x200

修改为(也可以在STM32CubeMX软件代码生成时修改)

Heap_Size      EQU     0x800

这里预计组装一个json格式的数据:

{  "name": "Huan",  "age": 19,  "city": "Mei Zhou"}

对于非常简单且固定的JSON格式数据,可以考虑直接使用snprintf或类似的字符串格式化函数来生成JSON字符串。

示例:

#include <stdio.h>  
#include <string.h>  
  
// 定义全局缓冲区  
#define BUFFER_SIZE 128  
char global_buffer[BUFFER_SIZE];  
  
// 函数声明  
void create_json_string(const char* name, int age, const char* city);  
  
// 主函数  
int main(void)  
{  
    create_json_string("Huan", 19, "Mei Zhou");  
    printf("Created JSON: %s\n", global_buffer);  
    return 0;  
}  
  
// 创建JSON字符串的函数  
void create_json_string(const char* name, int age, const char* city)  
{  
    // 使用snprintf将JSON字符串写入全局缓冲区  
    snprintf(global_buffer, BUFFER_SIZE, "{\"name\": \"%s\", \"age\": %d, \"city\": \"%s\"}", name, age, city);  
}


完整代码1

#include "main.h"  
#include <stdio.h>  
#include "jansson.h"  
#include <string.h> // 添加对字符串操作的支持  
  
// 函数声明  
char* create_json_string(const char* name, uint8_t age, const char* city);  
  
// 主函数  
int main(void)  
{  
    HAL_Init();  
    SystemClock_Config();  
    MX_GPIO_Init();  
    MX_DMA_Init();  
    MX_USART1_UART_Init();  
  
    while (1)  
    {  
        // 创建 JSON 字符串  
        char* json_str = create_json_string("Huan", 19, "Mei Zhou");  
        if (json_str != NULL) {  
            // 打印 JSON 字符串  
            printf("\r\nCreated JSON: %s\r\n", json_str);  
            // 释放 JSON 字符串内存  
            free(json_str); // 这里需要释放内存,因为json_dumps分配了新内存  
        }  
        HAL_Delay(5000);  
    }  
}  
  
// 创建 JSON 字符串的函数  
char* create_json_string(const char* name, uint8_t age, const char* city)  
{  
    // 创建 JSON 对象  
    json_t *root = json_object();  
    if (!root) {  
        fprintf(stderr, "Unable to create JSON object\r\n");  
        return NULL;  
    }  
  
    // 添加 name 字段  
    if (json_object_set_new(root, "name", json_string(name)) != 0) {  
        fprintf(stderr, "Unable to set name field\r\n");  
        json_decref(root);  
        return NULL;  
    }  
  
    // 添加 age 字段  
    if (json_object_set_new(root, "age", json_integer(age)) != 0) {  
        fprintf(stderr, "Unable to set age field\r\n");  
        json_decref(root);  
        return NULL;  
    }  
  
    // 添加 city 字段  
    if (json_object_set_new(root, "city", json_string(city)) != 0) {  
        fprintf(stderr, "Unable to set city field\r\n");  
        json_decref(root);  
        return NULL;  
    }  
  
    // 将 JSON 对象转换为字符串  
    char *jsonString = json_dumps(root, JSON_INDENT(2));  
    if (!jsonString) {  
        fprintf(stderr, "Unable to dump JSON string\r\n");  
        json_decref(root);  
        return NULL;  
    }  
  
    // 释放 JSON 对象  
    json_decref(root);  
    return jsonString;  
}

代码1运行效果:

完整代码2

如果像组装多重嵌套json对象的话,例如:
 

{  
  "id": "123",  
  "params": {  
    "name": {  
      "value": "Huan"  
    },  
    "age": {  
      "value": 19  
    },  
    "city": {  
      "value": "Mei Zhou"  
    }  
  }  
}

#include "main.h"  
#include <stdio.h>  
#include "jansson.h"  
  
typedef struct {  
    char city[10];  
    char name[10];  
    char id[10];  
    uint8_t age;  
} Student_TypeDef;  
  
char* create_json_string(const Student_TypeDef *student) {  
    json_t *root, *params, *name_obj, *age_obj, *city_obj;  
    char *json_str;  
  
    // 创建根对象  
    root = json_object();  
    if (!root) {  
        fprintf(stderr, "Failed to create root JSON object\r\n");  
        return NULL;  
    }  
  
    // 设置 id 字段  
    json_object_set_new(root, "id", json_string(student->id));  
  
    // 创建 params 对象  
    params = json_object();  
    if (!params) {  
        fprintf(stderr, "Failed to create params JSON object\r\n");  
        json_decref(root);  
        return NULL;  
    }  
  
    // 创建并设置 name 对象及其 value 字段  
    name_obj = json_object();  
    json_object_set_new(name_obj, "value", json_string(student->name));  
    json_object_set_new(params, "name", name_obj);  
  
    // 创建并设置 age 对象及其 value 字段  
    age_obj = json_object();  
    json_object_set_new(age_obj, "value", json_integer(student->age));  
    json_object_set_new(params, "age", age_obj);  
  
    // 创建并设置 city 对象及其 value 字段  
    city_obj = json_object();  
    json_object_set_new(city_obj, "value", json_string(student->city));  
    json_object_set_new(params, "city", city_obj);  
  
    // 将 params 对象添加到根对象中  
    json_object_set_new(root, "params", params);  
  
    // 将 JSON 对象转换为字符串  
    json_str = json_dumps(root, JSON_INDENT(0)); // 使用缩进使输出更美观(可选)  
  
    // 释放 JSON 对象(注意:json_dumps 之后不需要再释放 root,因为 json_dumps 会复制数据)  
    json_decref(root);  
  
    return json_str;  
}  
  
int main(void) {  
    HAL_Init();  
    SystemClock_Config();  
    MX_GPIO_Init();  
    MX_DMA_Init();  
    MX_USART1_UART_Init();  
  
    printf("Hello World!\r\n");  
  
    while (1) {  
        Student_TypeDef student = {"Mei Zhou", "Huan", "123", 19};  
        char *json_str = create_json_string(&student);  
        if (json_str) {  
            printf("Generated JSON:\r\n%s\r\n", json_str);  
            free(json_str); // 释放动态分配的 JSON 字符串内存  
        } else {  
            printf("Failed to generate JSON\r\n");  
        }  
        HAL_Delay(5000);  
    }  
}

代码2运行效果:



补充

 在最后组装json数据时,这里可以填一些参数

char *jsonString = json_dumps(root, JSON_INDENT(2));  

分别为:

#define JSON_MAX_INDENT         0x1F
#define JSON_INDENT(n)          ((n) & JSON_MAX_INDENT)
#define JSON_COMPACT            0x20
#define JSON_ENSURE_ASCII       0x40
#define JSON_SORT_KEYS          0x80
#define JSON_PRESERVE_ORDER     0x100
#define JSON_ENCODE_ANY         0x200
#define JSON_ESCAPE_SLASH       0x400
#define JSON_REAL_PRECISION(n)  (((n) & 0x1F) << 11)
宏定义说明
JSON_MAX_INDENT0x1F最大缩进级别(用于格式化输出时的缩进限制)
JSON_INDENT(n)((n) & JSON_MAX_INDENT)设置JSON输出的缩进级别为n,实际缩进级别会被限制在JSON_MAX_INDENT范围内
JSON_COMPACT0x20生成紧凑的JSON字符串(无缩进和多余的空格)
JSON_ENSURE_ASCII0x40确保输出的JSON字符串仅包含ASCII字符,对非ASCII字符进行转义
JSON_SORT_KEYS0x80对JSON对象的键进行排序输出
JSON_PRESERVE_ORDER0x100保留JSON对象插入键值的顺序(不排序)
JSON_ENCODE_ANY0x200允许编码任何类型的JSON值(包括非标准的或自定义的类型)
JSON_ESCAPE_SLASH0x400对正斜杠(/)进行转义处理
JSON_REAL_PRECISION(n)(((n) & 0x1F) << 11)设置浮点数的精度为nn的有效范围是0到31)

用法:

char *jsonString = json_dumps(root, JSON_INDENT(2) | JSON_ENSURE_ASCII | JSON_REAL_PRECISION(5));

这个示例中,json_dumps函数被配置为:

  • 使用2个空格缩进
  • 确保输出为ASCII字符
  • 设置浮点数的精度为5


结尾(必读)

 这里注意一点:
如果Json解析或者组装代码是正确的,然后解析或者组装的内容与预期不符,很可能是程序中设置的堆大小不足,
解决方法:在启动文件中:startup_stm32f103xb.s中找到

Heap_Size      EQU     0x200

修改为(也可以在STM32CubeMX软件代码生成时修改)

Heap_Size      EQU     0x800


在json解析和组装代码中存在大量的if判断结果是否正确,为了代码的健壮性一般不建议删除这些判断

后续更新更多的API使用
 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

医学数据分析实训 项目三 关联规则分析预备项目---购物车分析

文章目录 1 预备项目关联规则分析实践———购物车分析1 产生频繁集2 产生关联规则 1 预备项目 关联规则分析实践———购物车分析 import warnings import numpy as np import pandas as pd from mlxtend.frequent_patterns import apriori from mlxtend.frequent_patterns …

【LVIO-SLAM】SVD分解,最小二乘与EKF

【LVIO-SLAM】SVD分解与应用推导 1.1 线性最小而二乘1.2 SVD分解算法流程问题描述算法流程算法复杂度总结 1.3 非线性最小二乘1.4 EKF融合 KF/ EKF推导过程 1.1 线性最小而二乘 针对A是任意矩阵的话使用SVD分解求解&#xff0c;其中U是AA转置的特征值&#xff0c;V是AA转置A的特…

iPhone 16 还剩一个月,微软开源新技术让手机以 6 倍速度提前跑上大模型

作者 | 微软亚洲研究院 责编 | 王启隆 出品 | AI 科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09; 随着人工智能技术的飞速发展&#xff0c;将大语言模型(LLMs)部署到边缘设备上已成为当前 AI 领域的一个热门趋势。这一趋势不仅体现在微软 Windows 11 AI PC 等产品…

DFN:Data Filtering Networks

论文:https://arxiv.org/abs/2309.17425 代码:Data Filtering Networks | Papers With Code 阿里最近又开源了视觉多模态模型 Qwen2-VL,视觉编码器升级了,所以抓紧补一下DFN Qwen1-VL视觉编码器:OpenClip 的 ViT-bigG-14Qwen2-VL视觉编码器:DFN 的 ViT本文重点: 1:用…

选择排序(C语言实现)

目录 1.基本思想 2.代码实现 代码思路 代码实现 代码测试 3.复杂度分析 1&#xff09;时间复杂度 2&#xff09;空间复杂度 4.特性总结 1.基本思想 选择排序是一种简单直观的比较排序算法。该算法的基本思想是在每一轮中选出当前未排序部分的最小&#xff08;或最大&a…

通义千问模型升级:2.5正式上线的使用体验

个人对比各AI大模型的使用体会 正在用的国内的AI大模型主要有“通义千问”、“文心一言”、“讯飞星火”&#xff0c;还有国外的"ChatGPT"和"Copilot"&#xff0c;我觉得"通义千问"进步神速&#xff0c;因此现在我最常使用的就是"通义千问&…

【C++】C++11-新的类功能和可变参数模板

1、新的类功能 1.1 默认成员函数 原来C类中&#xff0c;有6个默认成员函数&#xff1a; 构造函数、析构函数、拷贝构造函数、赋值运算符重载、取地址重载、const取地址重载 C11增加了两个&#xff1a;移动构造函数、移动赋值运算符重载 自己实现这两个函数在上一篇文章中已…

Shelly实测天工的音乐创作功能,写了一首歌,来听听效果

​ 大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 在数字时代的洪流中&#xff0c;我始终…

16、斑马设备的ppocer-4进行文字识别,和opencv-mobile中文显示

基本思想:手上有个斑马设备,是客户的,简单记录一下开发过程和工程项目,同时记录跟着android小哥学习了很多anroid的知识,转ppocr-4参考之前的ppocr-3转换即可,整个框架仍然使用c++ ncnn jni框架推理和现实,图像库使用opencv-mobile 一、首先转paddle-cor-4 到ncnn的框架…

计算机复试相关问题

泰勒展开式 泰勒展开的目的是用多项式拟合一般函数。 拟合方法&#xff1a;保证多项式与原函数在x0处0到∞阶导都相同。 泊松分布 博客详解推导过程&#xff1a;概率论–泊松分布 IPv4和IPv6 IP 协议&#xff08;Internet Protocol&#xff09;是网络层的核心协议&#xf…

简单的spring缓存 Cacheable学习

简单的spring缓存 Cacheable学习 1.需求 项目中有很多的方法查询的数据其实是不会经常变的&#xff0c;但是其整体的查询sql以及调用第三方数据获取数据花费的时间很长&#xff0c;现在考虑对此类型的接口进行优化&#xff0c;首先想到的是对其进行缓存操作&#xff0c;所以简…

【数据结构与算法】十大经典排序算法深度解析:冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序、计数排序、桶排序、基数排序

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​ 目录 引言 一、排序算法概述 排序算法简介 排序算法的分类 性能指标 二、十大排序算法…

小新 Pro13 + windows 11 家庭中文版(网络适配器及地址配置)

网络适配器位置及地址配置 网络适配器简介 计算机系统&#xff1a;网络适配器详解&#xff0c;全面剖析 网络适配器位置 不同于win11之前的版本&#xff0c;win11的网络适配器的位置如下&#xff1a; 1、右键 右下角的网络图标-》网络和internet设置-》高级网络设置-》可以…

Apache CVE-2021-41773 漏洞复现

1.打开环境 docker pull blueteamsteve/cve-2021-41773:no-cgid docker run -d -p 8080:80 97308de4753d 2.访问靶场 3.使用poc curl http://47.121.191.208:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd 4.工具验证

颍川陈氏——平民崛起的典范

园子说颍川 广州有一处老建筑“陈家祠”&#xff0c;豪华精美堪比皇宫&#xff0c;誉为“岭南建筑艺术明珠”、“新世纪羊城八景”之一&#xff0c;是全国文保单位&#xff0c;4A 级景区。主体建筑以中轴线三座厅堂为中心&#xff0c;由大小十九座单体建筑组成&#xff0c;占地…

通信工程学习:什么是VM虚拟机

VM&#xff1a;虚拟机 VM虚拟机&#xff08;Virtual Machine&#xff09;是一种通过软件模拟的计算机系统&#xff0c;它能够在物理计算机上模拟并运行多个独立的虚拟计算机系统。以下是关于VM虚拟机的详细解释&#xff1a; 一、VM虚拟机的定义与原理 定义&#xff1a; VM虚拟…

认知杂谈77《简单:通往高手的技巧》

内容摘要&#xff1a;          在信息爆炸、关系复杂的时代&#xff0c;简单是复杂背后的真谛。简单如“112”&#xff0c;是智慧的朴素呈现。简单有强大力量&#xff0c;像清泉般纯净&#xff0c;如“我爱你”简单却有力&#xff0c;基础财务知识也体现其在理财中的作…

鸿蒙开发(NEXT/API 12)【基础功能(使用剪贴板进行复制粘贴)】剪贴板服务

场景介绍 [剪贴板]为开发者提供数据的复制粘贴能力。 当需要使用复制粘贴等功能时&#xff0c;例如&#xff1a;复制文字内容到备忘录中粘贴&#xff0c;复制图库照片到文件管理粘贴&#xff0c;就可以通过剪贴板来完成。 约束限制 剪贴板内容大小<128MB。为保证剪贴板数…

拓维思注册机Tovos PowerLine4.0.19树障分析 Tovos SmartPlan2.0.0航线规划软件

Tovos PowerLine是功能强大的输电线路智能巡检系统&#xff01;这是一个专业且智能的软件&#xff0c;能够更准确的进行巡检和对线路设备进行精确的测量&#xff0c;通过获取高精度的点云来获取精准的三维路线的地形地貌、设备设施、途径的各种物体等来精确您的三维空间信息和三…

PostgreSQL的学习心得和知识总结(一百五十一)|[performance] PostgreSQL列对齐

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…