67、自定义通信帧协议解析

帧格式:方便自定义长度多种帧标识传输

格式规定

帧标识A 类型 备注
A<=0x0F 短帧 数据长度1字节
A>0x0F 长帧 数据长度2字节

短帧:帧标识 帧标识取反 帧用户数据字节数 用户数据…用户数据
长帧:帧标识 帧标识取反 帧用户数据字节数(高8位) 帧用户数据字节数(低8位) 用户数据…用户数据
注意:
帧标识符应尽量避免使用0x00/0xFF,因为出现概率过高,容易误识别
若需提高准确度,则可以使用此文档的协议通信帧协议解析和发送_裸机

使用方法

#include "stdio.h"
#include "stdint.h"
#include "math.h"
#include "frame_driver.h"

#define dDATA_SIZE 65537
int main()
{
	//自定义短帧内容
	uint8_t data[dDATA_SIZE] = { 0x01,0x00,0x03,0x01,0x00,\
	0x01,dIdentify_Invert(0x01),0x01,0x0A,\
	0x02,0x03,0x01,
	0x01, dIdentify_Invert(0x01),0x05,0x01,0x02,0x03,0x04,0x05,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x01, dIdentify_Invert(0x01),0x02,0x01,0x02,\
		0x01, 0x00, 0x03, 0x01, 0x00, \

	0x01, dIdentify_Invert(0x01),0x03,0x01,0x02,0x03,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x02, dIdentify_Invert(0x02), 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x03, dIdentify_Invert(0x03), 0x02, 0x01, 0x02, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x04, dIdentify_Invert(0x04), 0x03, 0x01, 0x02, 0x03, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x05, dIdentify_Invert(0x05), 0x03, 0x01, 0x02, 0x03, \
	0x1F, dIdentify_Invert(0x1F), dDataLength_MSB(2), dDataLength_LSB(2),0x0A,0x0B\
	};
	uint8_t data2[dDATA_SIZE];
	uint32_t i = 0, j = 0, num = 0;

	i = 0;
	data2[i++] = 0x1F;//定义长帧内容
	data2[i++] = dIdentify_Invert(0x1F);
	data2[i++] = dDataLength_MSB(dDATA_SIZE - 4);
	data2[i++] = dDataLength_LSB(dDATA_SIZE - 4);
	for (j = 0; j < dDATA_SIZE - 4; j++)data2[i++] = j % 0x0FF;

	frame_handler frame;
	if (frame_init(&frame, 5, dDATA_SIZE) < 0)return 0;创建5个帧资源,最大帧长度为dDATA_SIZE
	if (frame_identify_add(&frame, 0x01) < 0)return 0;//添加标识符0x01帧
	if (frame_identify_add(&frame, 0x02) < 0)return 0;
	if (frame_identify_add(&frame, 0x03) < 0)return 0;
	if (frame_identify_add(&frame, 0x04) < 0)return 0;
	if (frame_identify_add(&frame, 0x1F) < 0)return 0;
	frame_identify_add(&frame, 0x05);//超过帧资源添加0x05标识符帧失败

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出,数据只能在此轮使用,下轮会进行内存覆盖,其他地方需要使用可以复制走
	}

	for (i = 0; i < dDATA_SIZE; i++)//查找短帧
	{
		if (frame_find(&frame, data[i]) < 0)continue;
		frame_data_printf(frame.data_rx);
	}

	//中途放弃之前的查找
	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (i == 4)frame_find_clear(&frame);//清空查找器
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出
	}

	frame_DeInit(&frame);//销毁帧资源

	
	uint8_t *pdata = NULL, send[6] = {0};
	pdata = frame_format_generate(0x0A, 2, send);//生成短帧格式:0x0A 0xF5 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 5; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}

	pdata = frame_format_generate(0x1A, 2, send);//生成长帧格式:0x0A 0xE5 0x00 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 6; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
注意:

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出,数据只能在此轮使用,下轮会进行内存覆盖,其他地方需要使用可以复制走
	}

frame_find(&frame, data2[i])查找到数据后必须当轮使用,下一次查找会进行内存覆盖,导致数据丢失,若他地方需要使用可以复制走

源文件

frame_driver.h

#ifndef _frame_driver_H_
#define _frame_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"

#include "stdio.h"
#define dFrame_LOG(...) printf(__VA_ARGS__) //日志输出

#define dIdentify_Invert(id) ((~id) & 0xFF)//标识符取反
#define dDataLength_MSB(len) ((len>>8)&0xFF)//截取数据长度高8位
#define dDataLength_LSB(len) (len&0xFF)//截取数据长度低8位
#define dDataLength_Merge(MSB,LSB) (((((uint16_t )MSB) << 8)|(uint16_t )LSB) & 0xFFFF)//合并得到长帧的数据长度

typedef struct
{
	uint8_t number;//帧种类数
	uint8_t pos;//帧标识集可用位置
	uint8_t *pbuf;//所有帧标识
}Frame_Identify_StructDef;//帧标识集

typedef struct
{
	uint32_t size; //帧缓冲区字节数
	uint8_t *pbuf;//缓冲区
	uint32_t pos;//位置点
}Frame_Buffer_StructDef;//缓冲区

typedef enum
{
	eFrame_DataState_Find = 0,//查找中
	eFrame_DataState_Receive,//接收数据
	eFrame_DataState_Complete//接收完毕
}Frame_DataState_EnumDef;//帧接收状态

typedef struct
{
	Frame_DataState_EnumDef state;//帧接收状态
	uint8_t identify;//接收的帧标识
	uint32_t size;//用户数据字节数
	uint8_t *pbuf;//帧用户数据缓冲区;注:不含帧头、数据字节数
}Frame_Data_StructDef;

typedef struct
{
	//内部变量区域:请勿修改
	uint8_t state;//帧状态:0--不可用,!0--可用
	Frame_Identify_StructDef identify;//帧集合
	Frame_Buffer_StructDef rx;//接收缓冲区	

	//共享变量区域
	Frame_Data_StructDef data_rx;//接收的数据
}frame_handler;

extern int frame_init(frame_handler *p, uint8_t number, uint32_t rx_size);
extern void frame_DeInit(frame_handler *p);
extern int frame_identify_add(frame_handler *p, uint8_t identify);
extern int frame_find(frame_handler *p, uint8_t data);
extern int frame_find_clear(frame_handler *p);
extern void frame_data_printf(Frame_Data_StructDef data);
extern uint8_t *frame_format_generate(uint8_t identify, uint32_t size, uint8_t *pbuf);

#ifdef __cplusplus
}
#endif
#endif

frame_driver.c

/**********************************************************************
*file:任意帧收发
*author:残梦
*versions:V2.0
*date:2024.3.20
*note:
格式规定:
帧标识A	类型	备注
A<=0x0F	短帧	数据长度1字节
A>0x0F	长帧	数据长度2字节

短帧:帧标识 帧标识取反 帧用户数据字节数									用户数据...用户数据
长帧:帧标识 帧标识取反 帧用户数据字节数(高8位) 帧用户数据字节数(低8位)  用户数据...用户数据
注意:
帧标识符应尽量避免使用0x00/0xFF,因为出现概率过高,容易误识别

使用方法:

#include "stdio.h"
#include "stdint.h"
#include "math.h"
#include "frame_driver.h"

#define dDATA_SIZE 65537
int main()
{
	//自定义短帧内容
	uint8_t data[dDATA_SIZE] = { 0x01,0x00,0x03,0x01,0x00,\
	0x01,dIdentify_Invert(0x01),0x01,0x0A,\
	0x02,0x03,0x01,
	0x01, dIdentify_Invert(0x01),0x05,0x01,0x02,0x03,0x04,0x05,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x01, dIdentify_Invert(0x01),0x02,0x01,0x02,\
		0x01, 0x00, 0x03, 0x01, 0x00, \

	0x01, dIdentify_Invert(0x01),0x03,0x01,0x02,0x03,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x02, dIdentify_Invert(0x02), 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x03, dIdentify_Invert(0x03), 0x02, 0x01, 0x02, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x04, dIdentify_Invert(0x04), 0x03, 0x01, 0x02, 0x03, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x05, dIdentify_Invert(0x05), 0x03, 0x01, 0x02, 0x03, \
	0x1F, dIdentify_Invert(0x1F), dDataLength_MSB(2), dDataLength_LSB(2),0x0A,0x0B\
	};
	uint8_t data2[dDATA_SIZE];
	uint32_t i = 0, j = 0, num = 0;

	i = 0;
	data2[i++] = 0x1F;//定义长帧内容
	data2[i++] = dIdentify_Invert(0x1F);
	data2[i++] = dDataLength_MSB(dDATA_SIZE - 4);
	data2[i++] = dDataLength_LSB(dDATA_SIZE - 4);
	for (j = 0; j < dDATA_SIZE - 4; j++)data2[i++] = j % 0x0FF;

	frame_handler frame;
	if (frame_init(&frame, 5, dDATA_SIZE) < 0)return 0;创建5个帧资源,最大帧长度为dDATA_SIZE
	if (frame_identify_add(&frame, 0x01) < 0)return 0;//添加标识符0x01帧
	if (frame_identify_add(&frame, 0x02) < 0)return 0;
	if (frame_identify_add(&frame, 0x03) < 0)return 0;
	if (frame_identify_add(&frame, 0x04) < 0)return 0;
	if (frame_identify_add(&frame, 0x1F) < 0)return 0;
	frame_identify_add(&frame, 0x05);//超过帧资源添加0x05标识符帧失败

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出
		//查找到数据后必须当轮使用,下一次查找会进行内存覆盖,导致数据丢失,若他地方需要使用可以复制走
	}

	for (i = 0; i < dDATA_SIZE; i++)//查找短帧
	{
		if (frame_find(&frame, data[i]) < 0)continue;
		frame_data_printf(frame.data_rx);
	}

	//中途放弃之前的查找
	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (i == 4)frame_find_clear(&frame);//清空查找器
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出
	}

	frame_DeInit(&frame);//销毁帧资源


	uint8_t *pdata = NULL, send[6] = {0};
	pdata = frame_format_generate(0x0A, 2, send);//生成短帧格式:0x0A 0xF5 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 5; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}

	pdata = frame_format_generate(0x1A, 2, send);//生成长帧格式:0x0A 0xE5 0x00 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 6; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}
	return 0;
}


**********************************************************************/
#include "frame_driver.h"
#include "stdlib.h"
#include "string.h"

static int frame_identify_find(Frame_Identify_StructDef identify, uint8_t id);

/****************************************
@function:匹配帧标识符集合
@param:identify--标识符集合
	id--待匹配的标识符
@return:-1--失败,0--成功
@note:
****************************************/
static int frame_identify_find(Frame_Identify_StructDef identify, uint8_t id)
{
	uint8_t i = 0;

	for (i = 0; i < identify.pos; i++)
	{
		if (identify.pbuf[i] == id)return 0;
	}
	return -1;
}

/****************************************
@function:帧资源初始化
@param:p--帧句柄
	number--帧种类数,范围[1,255]
	rx_size--帧接收缓冲区字节数,等于最大帧长度,范围[4,uint32_t]
@return:
	0--成功
	-1:参数错误
	-2:内存分配失败
@note:
****************************************/
int frame_init(frame_handler *p, uint8_t number, uint32_t rx_size)
{
	if ((p == NULL) || (number == 0) || (rx_size < 4))return -1;
	p->state = 0;
	p->identify.pbuf = (uint8_t *)malloc(number);
	if (p->identify.pbuf == NULL)
	{
		dFrame_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
	p->identify.number = number;
	p->identify.pos = 0;

	p->rx.pbuf = (uint8_t *)malloc(rx_size);
	if (p->rx.pbuf == NULL)
	{
		dFrame_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
	p->rx.size = rx_size;
	p->rx.pos = 0;

	p->data_rx.state = eFrame_DataState_Find;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;

	p->state = 1;
	return 0;
}

/****************************************
@function:帧资源销毁
@param:p--帧句柄
@return:void
@note:
****************************************/
void frame_DeInit(frame_handler *p)
{
	if (p == NULL)return;
	p->state = 0;
	if (p->identify.pbuf != NULL)free(p->identify.pbuf);
	p->identify.pbuf = NULL;
	p->identify.number = 0;
	p->identify.pos = 0;
	if (p->rx.pbuf != NULL)free(p->rx.pbuf);
	p->rx.pbuf = NULL;
	p->rx.size = 0;
	p->rx.pos = 0;

	p->data_rx.state = eFrame_DataState_Find;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;
}

/****************************************
@function:添加待查找的帧标识
@param:p--帧句柄
	identify--帧标识
		格式规定:
		帧标识	类型	备注
		A<=0x0F	短帧	数据长度1字节
		A>0x0F	长帧	数据长度2字节

		短帧:帧标识 帧标识取反 数据字节数 数据...数据
		长帧:帧标识 帧标识取反 数据字节数(高8位) 数据字节数(低8位) 数据...数据
@return:
	0:成功
	-1--参数错误
	-2:添加失败
@note:添加重复帧标识无效
****************************************/
int frame_identify_add(frame_handler *p, uint8_t identify)
{
	uint8_t i = 0;
	if (p == NULL)return -1;
	if (p->state == 0)return -1;
	if (p->identify.pos >= p->identify.number)return -2;
	while (i < p->identify.pos)
	{
		if (p->identify.pbuf[i++] == identify)return -2;
	}
	p->identify.pbuf[p->identify.pos++] = identify;
	return 0;
}

/****************************************
@function:数据接收并匹配帧集合
@param:p--帧句柄
	data--新数据
@return:
	0:识别到帧数据,数据信息查看p->data_rx结构体
	-1:参数异常|帧未初始化
	-2:帧查找中
	-3:数据接收中
	-4:接收缓冲区空间不足,原因:初始化的帧资源大小低于帧总长度
@note:
****************************************/
int frame_find(frame_handler *p, uint8_t data)
{
	uint32_t i = 0;
	uint16_t len = 0;

	if (p == NULL)return -1;
	if (p->state == 0)return -1;
	if (p->identify.pos == 0)return -1;//没有待识别的帧标识 
	switch (p->data_rx.state)
	{
	case eFrame_DataState_Find:
	{
		p->rx.pbuf[p->rx.pos++] = data;
		if (p->rx.pos < 4)return -2;

		len = (p->rx.pbuf[0] <= 0x0F) ? p->rx.pbuf[2] : dDataLength_Merge(p->rx.pbuf[2], p->rx.pbuf[3]);
		if ((p->rx.pbuf[0] != dIdentify_Invert(p->rx.pbuf[1])) || (len == 0))//帧标识不对|数据长度为0
		{
			//数据移除1字节
			for (i = 1; i < p->rx.pos; i++)p->rx.pbuf[i - 1] = p->rx.pbuf[i];
			p->rx.pos--;
			return -2;
		}
		if (frame_identify_find(p->identify, p->rx.pbuf[0]) < 0)
		{
			//数据移除1字节
			for (i = 1; i < p->rx.pos; i++)p->rx.pbuf[i - 1] = p->rx.pbuf[i];
			p->rx.pos--;
			return -2;
		}

		p->data_rx.identify = p->rx.pbuf[0];
		p->data_rx.size = len;
		p->data_rx.pbuf = (p->data_rx.identify > 0x0F) ? (&(p->rx.pbuf[4])) : (&(p->rx.pbuf[3]));
		if ((p->data_rx.identify > 0x0F) || (p->data_rx.size > 1))//长帧 或 短帧数据长度为1
		{
			p->data_rx.state = eFrame_DataState_Receive;
			return -3;
		}

		//数据接收完毕:短帧数据长度1
		p->data_rx.state = eFrame_DataState_Complete;
		return 0;
	}
	case eFrame_DataState_Receive:
	{
		if (p->rx.pos >= p->rx.size)
		{
			dFrame_LOG("Error[%s-line:%d]:Insufficient receive buffer space\n", __func__, __LINE__);
			return -4;
		}
		p->rx.pbuf[p->rx.pos++] = data;
		len = (p->data_rx.identify > 0x0F) ? (p->rx.pos - 4) : (p->rx.pos - 3);
		if (len < p->data_rx.size)return -3;//继续接收
		p->data_rx.state = eFrame_DataState_Complete;
		return 0;
	}
	case eFrame_DataState_Complete:
	{
		p->rx.pos = 0;
		p->rx.pbuf[p->rx.pos++] = data;
		p->data_rx.identify = 0;
		p->data_rx.size = 0;
		p->data_rx.pbuf = NULL;
		p->data_rx.state = eFrame_DataState_Find;
		return -2;
	}
	}
	return -1;
}

/****************************************
@function:帧查找器清空
@param:p--帧句柄
@return:void
@note:
****************************************/
int frame_find_clear(frame_handler *p)
{
	if (p == NULL)return -1;
	if (p->state == 0)return -1;

	p->rx.pos = 0;
	p->data_rx.state = eFrame_DataState_Find;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;
	return 0;
}

/****************************************
@function:帧接收信息打印
@param:data--接收到的帧数据
@return:void
@note:
****************************************/
void frame_data_printf(Frame_Data_StructDef data)
{
	uint32_t i = 0;

	dFrame_LOG("Identify=0x%0X size=%d", data.identify, data.size);
	for (i = 0; i < data.size; i++)
	{
		if (i == 0)dFrame_LOG(" data{0x%0x", data.pbuf[i]);
		else dFrame_LOG(",0x%0x", data.pbuf[i]);
	}
	if (i != 0)dFrame_LOG("}\n");
	else dFrame_LOG("\n");
}

/****************************************
@function:生成帧格式
@param:identify--帧标识符
	size--帧用户数据字节数,不能为0
	pbuf--帧缓冲区,生成的帧数据放置在此缓冲区,起始位置pbuf[0]
@return:
	NULL:生成失败,参数错误
	!NULL:帧用户数据起始地址
@note:
	注意生成的帧总长度为:
	短帧(identify <= 0x0F):(size+3)字节
	长帧(identify > 0x0F):(size+4)字节
	此函数会清0缓冲区
****************************************/
uint8_t *frame_format_generate(uint8_t identify, uint32_t size, uint8_t *pbuf)
{
	if ((pbuf == NULL) || (size < 1))return NULL;
	memset(pbuf, 0, (size + ((identify > 0x0F) ? 4 : 3)));
	pbuf[0] = identify;
	pbuf[1] = dIdentify_Invert(identify);
	if (identify > 0x0F)
	{
		pbuf[2] = dDataLength_MSB(size);
		pbuf[3] = dDataLength_LSB(size);
		return &pbuf[4];
	}
	pbuf[2] = size;
	return &pbuf[3];
}

网盘下载:
链接:https://pan.baidu.com/s/1CUGxA0JEIBjF0F6YXyMDnA
提取码:pjgp

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

卸载应用无残留,App Cleaner Uninstaller Pro助你轻松管理Mac

App Cleaner & Uninstaller Pro是一款专为Mac用户设计的强大应用程序清理和卸载工具。这款软件拥有出色的卸载功能&#xff0c;能够彻底删除不再需要的应用程序及其相关文件和数据&#xff0c;确保Mac磁盘空间得到高效释放。同时&#xff0c;其强大的搜索功能可以快速找到与…

机器视觉系统选型-镜头参数

镜头参数&#xff1a; 光圈&#xff1a;光圈是一个用来控制镜头通光量的装置 &#xff0c;表示光圈大小我们是用光圈值&#xff08;F值&#xff09; &#xff0c;如F1.4&#xff0c;F2&#xff0c;F2.8 焦距&#xff08;Focus&#xff09;&#xff1a;透镜中心到其焦点的距离 景…

蓝桥杯刷题(十二)

1.答疑 代码 n int(input()) L [] for i in range(n):a,b,c map(int,input().split())A ab # 进入和答疑时间B abc # 个人总用时L.append([A,B]) L.sort(keylambda x:x[1]) # 个人总用时短的优先 ans tmp 0 # ans为发消息时刻&#xff0c;tmp为前一个人的总用时 for i …

C++ —— 类和对象(终)

目录 1. 日期类的实现 1.1 前置 和 后置 重载 1.2 >> 和 << 的重载 2. const 成员 3. 取地址及const取地址操作符重载 4. 再谈构造函数 4.1 构造函数体赋值 4.2 初始化列表 4.3 隐式类型转换 4.4 explict 关键字 5. static 成员 5.1 概念 5.2 特性 …

最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载

最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载 梨花带雨播放器基于thinkphp6开发的XPlayerHTML5网页播放器前台控制面板,支持多音乐平台音乐解析。二开内容:修复播放器接口问题,把接口本地化,但是集成外链播放器接口就不本地化了,我花钱找人写的理解下…

iOS图片占内存大小与什么有关?

1. 问&#xff1a;一张图片所占内存大小跟什么有关&#xff1f; 图片所占内存大小&#xff0c;与图片的宽高有关 我们平时看到的png、jpg、webp这些图片格式&#xff0c;其实都是图片压缩格式。通过对应的算法来优化了大小以节省网络传输与本地保存所需的资源。 但是当我们加…

vant4中如何修改Dialog弹框内容的字体大小

最近在开发一个移动端的需求&#xff0c;用的UI组件库是vant4 简单地总结一下&#xff0c;如何修改Dialog弹框内容的字体大小 我们先看一下Dialog弹框简单的使用 import { showConfirmDialog } from vant;showConfirmDialog({title: 标题,message:如果解决方法是丑陋的&#…

抖音视频无水印下载软件|视频批量提取工具

视频无水印下载软件 随着视频平台上涌现出越来越多精彩的视频内容&#xff0c;很多用户希望能够下载自己喜爱的视频进行保存或分享。为了满足用户需求&#xff0c;我们推出了专业的视频无水印下载软件&#xff0c;让您可以轻松快捷地获取喜欢的视频内容。以下是该软件的安装教…

Sealos 云开发:Laf 出嫁了,与 Sealos 正式结合!

千呼万唤始出来&#xff0c;Laf 云开发最近已正式与 Sealos 融合&#xff0c;入住 Sealos&#xff01;大家可以登录 Sealos 公有云 体验和使用&#xff0c;现在正式介绍一下 Sealos 云开发。 Sealos 云开发是什么&#xff1f; 如图&#xff0c;我们把 Laf 融合到 Sealos 中去了…

MySQL如何用phpMyAdmin创建定时任务事件来执行SQL语句删除_edit_lock和_edit_last?

前面跟大家分享了『WordPress如何批量删除wp_postmeta数据表无用的_edit_lock和_edit_last数据&#xff1f;』和『宝塔面板在计划任务中怎么执行SQL语句删除_edit_lock和_edit_last&#xff1f;』&#xff0c;但是有些站长并不是使用宝塔面板&#xff0c;那么我们如何时间定时删…

AIGC:让生成式AI成为自己的外脑

前言 在数字化浪潮席卷全球的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到了我们生活的方方面面。其中&#xff0c;生成式AI以其独特的魅力&#xff0c;正逐渐改变我们与世界的交互方式。AIGC&#xff08;人工智能生成内容&#xff09;作为生成式AI的重要应用…

灯塔:CSS笔记(4)

伪类选择器&#xff1a; 1.作用与优势&#xff1a; 1.作用&#xff1a;根据元素在HTML中的结构关系查找元素 2.优势&#xff1a;减少对于HTML中类的依赖&#xff0c;有利于保持代码的整洁 3.场景&#xff1a;常用于查找某父级选择器中的子元素 2.选择器 选择器说明E:first-c…

数据库的基本概念和安装MYSQL数据库

目录 一、数据库的发展 1、文件管理系统的缺点 2、数据库管理系统DBMS的优点 3、数据库管理系统&#xff08;DBMS&#xff09; 3.1DBMS的功能 3.2DBMS的工作模式 4、数据库系统的发展 5、数据库管理系统的架构 6、数据库管理系统分类 二、RDBMS关系型数据库的基本介绍…

软考 网工 每日学习打卡 2024/3/19

学习内容 第8章 网络安全 本章主要讲解网络安全方面的基础知识和应用技术。针对考试应该掌握诸如数据加密、报文认 证、数字签名等基本理论&#xff0c;在此基础上深入理解网络安全协议的工作原理&#xff0c;并能够针对具体的 网络系统设计和实现简单的安全解决方案。 本章共有…

Java学习笔记21——使用JDBC访问MySQL数据库

JDBC&#xff08;Java Database Connectivity&#xff0c;Java数据库连接&#xff09;是应用程序编程借口&#xff08;API&#xff09;&#xff0c;描述了一套访问关系数据库的标准Java类库。可以在程序中使用这些API&#xff0c;连接到关系数据库&#xff0c;执行SQL语句&…

由浅到深认识C语言(7):预处理二进制

该文章Github地址&#xff1a;https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.csdn…

Oracle19C静默安装教程

一、安装前的准备 1、安装Linux操作系统 红帽Linux安装教程 2、配置网络源或者本地源 网络源&#xff1a;网络源配置方法 本地源&#xff1a;本地源配置方法 3、hosts文件配置 配置hostname&#xff1a; hostnamectl set-hostname p19c配置hosts文件&#xff1a; cat &…

从零开始写 Docker(七)---实现 mydocker commit 打包容器成镜像

本文为从零开始写 Docker 系列第七篇&#xff0c;实现类似 docker commit 的功能&#xff0c;把运行状态的容器存储成镜像保存下来。 完整代码见&#xff1a;https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识&#xff1a; 核心原…

多个线程交替打印ABC

多个线程交替打印ABC package 多个线程交替打印ABC;import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier;/*** Created with IntelliJ IDEA.** Author: AlenXu* Date: 2024/03/20/10:10* Description:*/ public class ThreadLoopP…

数字功放VS模拟功放,选择适合你的音频解决方案

数字功放和模拟功放是音频系统中常用的两种功放技术&#xff0c;适用于不同的音频应用&#xff0c;都具有各自的优势和特点。本文将为您详细介绍数字功放和模拟功放的差异&#xff0c;并帮助您找到适合自己的音频解决方案。 1、数字功放是一种利用数字信号处理技术的功放。它将…
最新文章