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

3.3.2 应用层协议设计protobuf(二进制序列化协议)

文章目录

  • 3.3.2 应用层协议设计protobuf(二进制序列化协议)
    • 1. 什么是协议设计
      • 什么是协议
      • 为什么说进程间通信就需要协议,而不是客户端与服务端之间
      • 为什么需要自己设计协议
    • 2. 判断消息的完整性->区分消息的边界
      • 1.固定长度
      • 2. 特定符号
      • 3. 固定消息头加消息体
      • 4. 序列化后buffer前面加上一个字符流的头部,有个字符加上信息长度
    • 3. 协议设计
      • 1. 重点
      • 2. 设计范例
        • 1. IM即时通讯
        • 2. 云平台节点服务器
        • 3, nginx反向代理协议
        • 4. http
        • 5. redis
      • 3. 序列化方法
        • 1. 序列化和反序列化概念
        • 2. 什么情况下需要序列化
        • 3. 常见序列化方法(xml,json,protocolbuffer)
    • 4. protobuf使用
      • protobuf协议的工作流程:
      • protobuf为什么省字节:
      • 3. protobuf使用实例以及工程经验
      • 4. protobuf编码原理
      • 5. protobuf的数据组织,协议消息升级
    • 5. 扩充oneof
    • 6.示例

3.3.2 应用层协议设计protobuf(二进制序列化协议)

重点:
1.掌握通信协议设计原理
2.理解protobuf为什么快
3.掌握protobuf怎么在工程使用

1. 什么是协议设计

什么是协议

协议(Protocol) 是一套规则或约定,用于规范不同实体之间通信的格式、内容、顺序以及如何处理错误等。

在计算机系统中:

  • 协议定义了数据如何编码、传输与解释
  • 类似现实生活中的“语言”:如果你我要对话,必须说同一种语言、知道语序、停顿、语义。

比如:

  • TCP 协议规定了传输层如何建立连接、如何可靠传输数据;
  • HTTP 协议规定了浏览器和服务器之间如何请求和响应网页;
  • 自定义的“消息格式”也是协议

为什么说进程间通信就需要协议,而不是客户端与服务端之间


客户端与服务端之间的通信就是一种进程间通信(跨主机或本地)。进程间通信(IPC)包括:

  • 本地 IPC:如共享内存、管道、消息队列;
  • 网络 IPC:如 TCP/IP 通信(典型是客户端-服务器模式)。

不管哪种,只要两个独立进程之间要交换数据,就必须达成“怎么解释这些数据”的共识 —— 即需要 协议

为什么需要自己设计协议

原因描述
效率需求可能只需要几个字节传输,不需要完整 HTTP 报文(太臃肿)
场景定制系统消息结构是固定/可预测的,用现成协议反而复杂
资源受限在嵌入式或无人机/无人船等平台,资源宝贵,自己设计协议可以压缩带宽和内存使用
安全性有些自定义协议对攻击者来说是“黑盒”,可降低被攻击面
功能扩展方便可以灵活设计ACK机制、心跳包、数据校验等机制

举例:简单的自定义协议


[HEAD][TYPE][LEN][DATA][CRC]
  • HEAD:帧头(0xAA55);
  • TYPE:消息类型(如心跳/导航指令);
  • LEN:数据长度;
  • DATA:数据本体;
  • CRC:校验码。

这种协议既精简又高效,适用于 USV/UAV 协同这类低时延、低资源的跨平台通信。

2. 判断消息的完整性->区分消息的边界

1.固定长度

  • 每条消息占用固定的字节数,没有冗余的长度字段
  • 接收方按照“每N字节一条消息”读取和处理

优点:

  • 解析速度极快,无需动态判断;
  • 非常适合带宽有限、实时性强的嵌入式或硬实时系统;
  • 实现简单,不需要缓冲区滚动或多线程解析器。

缺点:

  • 缺乏灵活性,不能应对可变数据量;
  • 可能造成 空间浪费(实际数据 < 固定长度);
  • 不适合复杂的交互系统或信息种类过多的系统。

2. 特定符号

  • 用特殊字符/标志表示消息开始和结束,如:

<SOF>数据内容<EOF>

举例:

  • GPS NMEA 协议:$GPRMC,.....*校验码\r\n
  • 串口通信中常见 <STX>...<ETX>

优点:

  • 可变长度支持;
  • 清晰易读,调试方便(尤其串口、日志里常用)。

缺点:

  • 需要转义特殊字符(若内容中也出现SOF/EOF字符);
  • 协议解析器略复杂
  • 对字节流完整性要求较高(中间SOF/EOF丢失会错位)

3. 固定消息头加消息体

  • 报文格式一般为:

| HEAD | TYPE | LENGTH | BODY | CRC |
  • 解析时先识别HEAD,再读取LENGTH字段确定接收多少字节。

举例:

  • 工业协议如 Modbus、CAN、无人机MAVLink

优点:

  • 通用性最强;
  • 支持变长数据,适合异构系统通信;
  • 能加校验码(CRC)、消息ID(用于ACK、重传等)等高级特性

缺点:

  • 相比纯固定长度复杂

4. 序列化后buffer前面加上一个字符流的头部,有个字符加上信息长度

原理

  • 先用 JSON、Protobuf 等序列化数据;
  • 再加上前缀(如总长度),如:

[4字节长度][序列化后的内容]

举例:

  • Redis 使用 RESP 协议(文本前缀 + 换行符);
  • HTTP/2、gRPC、Kafka 等使用 [length][payload];
  • socket.io、Thrift 等也有类似机制。

优点:

  • 灵活性最高;
  • 可嵌套结构体(如嵌入式系统与服务器对接);
  • 配合现成的库(Protobuf/Flatbuffers)效率也很高

缺点:

  • 要引入额外序列化库;
  • 消息体结构需要双方都了解(或共享 schema)
  • 带宽、内存资源敏感的设备慎用(不适合裸片/超轻系统)

3. 协议设计

1. 重点

  1. 消息边界
  2. 版本区分
  3. 消息类型区分
  4. 消息budy序列化协议选择

2. 设计范例

1. IM即时通讯
  1. 消息边界:第一个字节作为帧的起始
  2. 版本号:靠前放
  3. appid:识别不同客户
  4. service_id:对应命令的分类组
  5. commend_id:分组里面的子命令
  6. seq_num:消息序号(业务序号)
  7. reserve:保留
    头有十六个字节
  8. body
2. 云平台节点服务器
  1. STAG:通信协议数据开始标记
  2. version:版本号
  3. checksum:校验和,crc校验
  4. type:协议体格式(json,xml,protobuf等)
  5. seqno:序列号
  6. length:报文长度
  7. reserve:保留
    头有十八个字节
  8. body
3, nginx反向代理协议

Nginx 自身协议不多,但它支持例如:

  • HTTP(标准格式)
  • FastCGI、GRPC、Websocket 转发协议
  • 内部也可做 X-Forwarded-For、X-Real-IP 等头部协议标注。

实践中经常会在 Header 中加自定义字段来传递用户/设备上下文

4. http

两个换行符之后就是body,复杂

5. redis

缺点:

  • 基于行文本协议,有前缀 *$ 等表示参数数量/长度;
  • 单行或多行结构都可以表示;
  • 高效解析、极简实现、支持 pipeline。

优点:

  • 文本协议,调试方便;
  • 对性能也进行了很好的优化

3. 序列化方法

1. 序列化和反序列化概念

序列化(Serialization)

将内存中的对象(数据结构)转换为可存储或传输的格式

常用于把:

  • 内存对象 → 字节流 / 字符串 / 文件 / 网络报文

比如把结构体 Person{name="Tom", age=25} 转换成:

  • "{"name":"Tom","age":25}"(JSON)
  • 0A 03 54 6F 6D 10 19(protobuf 编码)

反序列化:

把序列化后的格式重新转换回内存中的对象

它是序列化的逆过程,接收到字节流或字符串后重新还原成程序对象

2. 什么情况下需要序列化

场景一:网络通信

  • 客户端和服务端要通过网络传输结构化数据;
  • 需要把对象编码成“可发送的格式”;
  • 常用于 API 通信、微服务通信、远程调用(RPC)。

场景二:数据存储

  • 对象持久化到磁盘、缓存、数据库等;
  • 比如存储用户配置、本地缓存等。

场景三:跨语言/平台通信

  • 不同语言之间的数据交互(如 Python ↔ C++);
  • 需要通用协议(JSON、protobuf)
3. 常见序列化方法(xml,json,protocolbuffer)
序列化格式可读性压缩效率跨语言编码速度使用场景举例
JSON✅ 高❌ 一般✅ 强✅ 快Web API、配置文件
XML✅ 高❌ 差✅ 强❌ 慢配置、SOAP协议
protobuf❌ 差✅ 高✅ 强✅ 非常快微服务、IoT传输

JSON(JavaScript Object Notation)


{"name":"Alice","age":23}
  • 文本格式,易读易写;

XML(eXtensible Markup Language)


<person><name>Alice</name><age>23</age></person>
  • 结构清晰,冗余更高;

Protocol Buffers(Google 出品)


message Person {string name = 1;int32 age = 2;
}
  • 编译成高效二进制格式
  • 非常适合高性能、低带宽传输场景
  • 支持版本升级、字段可选

4. protobuf使用

由 Google 提出的一种语言无关、平台无关、可扩展的结构化数据序列化方法

IDL:接口描述语言‘

protobuf协议的工作流程:

(1)编写 .proto 文件(IDL,接口描述语言)


syntax = "proto3";message Person {int32 id = 1;string name = 2;string email = 3;
}

(2)用 protoc 编译器生成语言对应的代码


protoc --cpp_out=. person.proto

生成文件包括:

  • person.pb.h:头文件,包含类声明
  • person.pb.cc:源文件,包含实现

(3)在代码中使用


#include "person.pb.h"Person p;
p.set_id(123);
p.set_name("Alice");
p.set_email("alice@example.com");string data;
p.SerializeToString(&data);  // 序列化成二进制字符串Person p2;
p2.ParseFromString(data);    // 反序列化回来

(4)编译时记得加上 .pb.cc


g++ main.cpp person.pb.cc -lprotobuf -o myprog

protobuf为什么省字节:

1)只传编号,不传字段名

  • Protobuf 会将每个字段赋予一个唯一编号(比如 name = 2
  • 序列化时不会发送“name”,而是发送编号 2 + 内容
  • 这比 JSON 里 "name":"Alice" 要节省非常多

2)可变长度编码(Varint)

  • 小数字用更少字节表示,比如:
    • int32 id = 1; → 值为 5 时只用 1 个字节
  • 不像固定长度的 int32 总是占 4 字节

3)不传默认值

  • 字段没设置时不会被序列化(默认值省略)
  • 例如,string name = "" 不会写入输出数据

3. protobuf使用实例以及工程经验

  1. proto文件命名规则:工程名.模块名.proto
  2. proto命名空间
  3. 引用文件

import "auth/user.proto";message LoginRequest {auth.User user = 1;
}
  1. 多个平台使用同一份proto文件(独立git去维护这个git文件)

4. protobuf编码原理

  1. TLV结构
  • T(Tag):字段编号 + wire type
  • L(Length):字段长度(部分类型,如 string, bytes)
  • V(Value):字段值本身

例如:


message Person {int32 id = 1;string name = 2;
}

会被编码为:


[Tag=8][Varint=id] [Tag=18][Length][String=name]

2.为什么要用变长编码

原理(Base128 编码):

  • 一个字节只有 7 位存储有效数据,第 8 位(MSB)表示是否还有下一个字节。
  • 最后一字节的 MSB 为 0,其他为 1。
数值二进制Base128 表示(字节流)
1000000010x01
3001001011000xAC 0x02

优点:

  • 小整数压缩特别高效(如常见的 id、flag)
  • 节省带宽与存储

缺点:

  • 编码解析稍复杂(需 bit 操作)

和固定长度编码区别

类型描述优点缺点场景
可变长度(Varint)int32、int64、bool 等小数字更节省编解码复杂,性能略差id、flag、状态位、枚举等
固定长度fixed32、fixed64编解码快,CPU 缓存友好小数字浪费空间经纬度、时间戳、浮点数、hash值等

5. protobuf的数据组织,协议消息升级

  1. 新增字段

message User {uint32 id = 1;string name = 2;string email = 3; // 新增字段
}
  • 老版本:直接忽略 email
  • 新版本:可正常使用 email
  1. 删除字段的错误方式

message User {uint32 id = 1;// 删除 name = 2 (错误❌)
}

正确方式是:


message User {uint32 id = 1;reserved 2;reserved "name";
}
  1. 字段编号变动(大坑)

// 老版本
string nickname = 2;// 新版本(错误)
string nickname = 4;  // ❌ 改了 tag 编号

老版本程序会错误地把别的字段解析成 nickname,数据混乱


向前兼容 vs 向后兼容

兼容方向定义例子
向前兼容新代码能读取老数据老版本写的 protobuf,新代码能读
向后兼容老代码能读取新数据(忽略新增字段)老版本代码能跑新版消息

Protobuf 默认支持 向后兼容,即新增字段自动被老版本忽略

5. 扩充oneof

一种节省空间并简化协议字段表示的方法

  1. 可以安全添加新字段

message Action {oneof cmd {string login = 1;string logout = 2;string heartbeat = 3; // ✅ 安全新增}
}

兼容性说明

  • 向后兼容:老版本程序会忽略 heartbeat
  • 向前兼容:新版本能正常解析老版本发出的 login/logout
  1. 不可删除已有字段

// 错误示范
message Action {oneof cmd {string login = 1;// 删除 logout = 2 ❌}
}

即使客户端不再使用某个字段,也不要删除,应该使用 reserved


reserved 2;
reserved "logout";

6.示例

  1. message.proto

syntax = "proto3";
package demo;message HelloRequest {string name = 1;
}message HelloReply {string message = 1;
}

  1. main.cpp

#include <iostream>
#include "message.pb.h"int main() {demo::HelloRequest req;req.set_name("HIT");demo::HelloReply rep;rep.set_message("Hello " + req.name());std::cout << rep.message() << std::endl;return 0;
}

  1. CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(protobuf_demo)
#寻找系统中安装的 Protobuf 库
find_package(Protobuf REQUIRED)# 编译 .proto 文件为 .pb.h 和 .pb.cc
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS message.proto)#创建一个可执行程序 main,它会编译 main.cpp 和刚才生成的 .pb.cc 文件
add_executable(main main.cpp ${PROTO_SRCS} ${PROTO_HDRS})#把 protobuf 的库链接进可执行程序中,比如 libprotobuf.a 或 libprotobuf.so
target_link_libraries(main PRIVATE ${Protobuf_LIBRARIES})指定 .pb.h 的头文件路径,告诉编译器去哪里找
target_include_directories(main PRIVATE ${Protobuf_INCLUDE_DIRS})

  1. 编译步骤

mkdir build
cd build
cmake ..
make
./main
# 输出:Hello HIT

相关文章:

3.3.2 应用层协议设计protobuf(二进制序列化协议)

文章目录 3.3.2 应用层协议设计protobuf&#xff08;二进制序列化协议&#xff09;1. 什么是协议设计什么是协议为什么说进程间通信就需要协议&#xff0c;而不是客户端与服务端之间为什么需要自己设计协议 2. 判断消息的完整性->区分消息的边界1.固定长度2. 特定符号3. 固定…...

软件测试过程模型:v模型、w模型、x模型、H模型

软件测试流程 获取测试需求编写测试计划制定测试方案开发和设计测试用例执行测试提交缺陷报告测试分析与评审提交测试报告准备下一版本测试 软件测试过程模型 v模型 【V模型是线性的操作方式】 优点&#xff1a; 验收测试的标准是用户的需求&#xff0c;用户需求对应指导…...

设计模式-代理模式

虚代理 根据需要创建对象...

cocos Spine资源及加载

COCOS Spine 资源加载 创建 Canvas 以及Camera 再进行spine 拖入 提供40个实战酷炫技能spine文件&#xff1a; Spine文件下载...

约翰·麦卡锡:我的人工智能之梦

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 约翰麦卡锡&#xff1a;我的人工智能之梦 一、引言&#xff1a;计算机科学的传奇人物…...

Scrapy结合Selenium实现搜索点击爬虫的最佳实践

一、动态网页爬取的挑战 动态网页通过JavaScript等技术在客户端动态生成内容&#xff0c;这使得传统的爬虫技术&#xff08;如requests和BeautifulSoup&#xff09;无法直接获取完整的内容。具体挑战包括&#xff1a; 数据加载异步化&#xff1a;数据并非一次性加载&#xff…...

Oracle数据库数据编程SQL<9.3 数据库逻辑备份和迁移Data Pump (EXPDP/IMPDP) 导出、导入补充>

Oracle Data Pump 是 Oracle 10g 引入的高效数据迁移工具,相比传统的 EXP/IMP 工具,它提供了更强大的功能和显著的性能提升。以下是对 EXPDP 和 IMPDP 工具的全面讲解。 目录 一、高级功能扩展 1. 数据过滤与转换 2. 加密与安全 二、性能调优进阶 1. 并行处理优化 2. …...

Vue 3 + TypeScript 实现一个多语言国际化组件(支持语言切换与内容加载)

文章目录 一、项目背景与功能概览二、项目技术架构与依赖安装2.1 技术栈2.2 安装依赖 三、国际化组件实现3.1 创建 i18n 实例3.2 配置 i18n 到 Vue 应用3.3 在组件中使用国际化内容3.4 支持语言切换 四、支持类型安全4.1 添加类型支持4.2 自动加载语言文件 一、项目背景与功能概…...

RK3506+net9+VS2022跨平台调试C#程序

下载GetVsDbg.sh &#xff0c;这脚本会下载一个压缩包&#xff0c;然后解压缩&#xff0c;设置x权限等等。但是目标板子连不上&#xff0c;就想办法获取到下载路径&#xff0c;修改这个脚本&#xff0c;显示这个下载链接后&#xff0c;复制一下&#xff0c;用电脑下下来 修改好…...

c# 反射及优缺点

在C#中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时检查其自身的结构&#xff08;如类型、属性、方法等&#xff09;&#xff0c;以及动态地调用对象的方法或访问其属性。反射主要用于那些在编译时不知道具体类型信息&…...

基于SpringBoot的在线教育系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

吴恩达深度学习复盘(16)决策树|节点纯度与熵

决策树简介 决策树算法在很多应用中被使用&#xff0c;机器学习比赛中会经常见到&#xff0c;但在流行病学领域未受到太多关注。 决策树示例 —— 猫的分类 以经营猫收养中心为例&#xff0c;通过动物的耳朵形状、脸型、是否有胡须等特征&#xff0c;来训练一个分类器判断动…...

C++基础精讲-07

文章目录 1. const对象2. 指向对象的指针3. 对象数组4. c中const常见用法总结4.1 修饰常量4.2 修饰指针4.3 修饰函数参数4.4 修饰函数返回值4.5 修饰成员函数4.6 const对象 5. 赋值运算符函数&#xff08;补充&#xff09;5.1 概念5.2 默认赋值运算符函数局限5.3 解决办法 1. c…...

100个有用的AI工具 之 生成透明图像LayerDiffuse

Stable Diffusion是开源图像生成界的扛把子,最强的地方在于它的可控性,通过ControlNet,和一系列插件,可以非常精准地控制图像生成的需求。 今天介绍的是SD的一个插件LayerDiffuse,它可以帮助我们用SD生成透明的png图层。我们在用PS抠图的时候,对于头发、毛绒边这种图是非…...

springboot和springcloud的区别

1. ‌目的与功能‌ ‌1)Spring Boot‌: 主要用于快速构建独立的、生产级的 Spring 应用程序。它通过自动配置和嵌入式服务器等特性,简化了微服务的开发、启动和部署,使开发者能够专注于业务逻辑而非繁琐的配置。‌Spring Boot是一个快速开发的框架,旨在简化Java应用程序的开…...

前端操作document的小方法,主要功能-获取当前页面全部的a标签页,并根据链接中必要的字段进行判断,然后把这些链接放入iframe去打开

首先是一些小方法&#xff0c;有一个问题就是在不同源的页面中无法获取iframe中的dom const isInIframe window.parent ! window.self; console.log(是否在 iframe 中:, isInIframe); console.log(来源页面:, document.referrer); const isSame new URL(document.referrer).o…...

RocketMQ 03

今天是2025/04/14 21:58 day 20 总路线请移步主页Java大纲相关文章 今天进行RocketMQ 6,7,8 个模块的归纳 最近在忙毕设&#xff0c;更新有点慢&#xff0c;见谅 首先是RocketMQ 的相关内容概括的思维导图 6. 安全机制 6.1 ACL 访问控制 核心功能 权限分级&#xff1a;通过…...

基于项目管理的轻量级目标检测自动标注系统【基于 YOLOV8】

&#x1f431; AILabeler 是一个轻量级目标检测标注系统&#xff0c;专为 YOLO 系列模型设计&#xff0c;支持图像上传、标注框管理、类别设置、自动标注&#xff08;YOLOv8&#xff09;、导出多格式训练数据等功能。 项目已经发布至https://github.com/as501226107/AILabeler&…...

针对 Java从入门到精通 的完整学习路线图、各阶段技术点、CTO进阶路径以及经典书籍推荐。内容分阶段展开,兼顾技术深度与职业发展

以下是针对 Java从入门到精通 的完整学习路线图、各阶段技术点、CTO进阶路径以及经典书籍推荐。内容分阶段展开&#xff0c;兼顾技术深度与职业发展。 一、学习路线图分阶段详解 阶段1&#xff1a;Java基础入门&#xff08;3-6个月&#xff09; 目标&#xff1a;掌握Java核心…...

深度学习总结(13)

选择损失函数 为问题选择合适的损失函数&#xff0c;这是极其重要的。神经网络会采取各种方法使损失最小化&#xff0c;如果损失函数与成功完成当前任务不完全相关&#xff0c;那么神经网络最终的结果可能会不符合你的预期。因此&#xff0c;一定要明智地选择损失函数&#xf…...

AI测试引擎中CV和ML模型的技术架构

技术架构概述 1. 数据采集层 此层负责收集各种类型的数据,为后续的模型训练和测试提供基础。对于CV模型,主要采集图像、视频数据,可来源于摄像头、图像数据库等;对于ML模型,采集结构化数据(如表格数据)、非结构化数据(如文本数据)等,数据来源包括业务系统日志、传感…...

业务架构发展历史及相关技术应用介绍

1&#xff0c;单体架构 企业处于发展初期阶段&#xff0c;业务的开发量与用户的访问量较少的情况下&#xff0c;通常情况会将业务编写在一个应用中&#xff0c;由一个web容器完成部署调用。如下图&#xff0c;一个应用中所有的功能模块写在一个war包中&#xff0c;功能模块的代…...

Java栈与队列深度解析:结构、实现与应用指南

一、栈与队列核心概念对比 特性栈 (Stack)队列 (Queue)数据原则LIFO&#xff08;后进先出&#xff09;FIFO&#xff08;先进先出&#xff09;核心操作push(入栈)、pop(出栈)、peek(查看栈顶)offer(入队)、poll(出队)、peek(查看队首)典型应用函数调用栈、括号匹配、撤销操作任…...

CentOS DVD完整版与Minimal版的区别

文章目录 一、体积与内置软件&#xff1a;从“大而全”到“小而精”二、安装体验&#xff1a;开箱即用 vs 高度定制三、适用场景&#xff1a;桌面与服务器的分水岭四、后续配置&#xff1a;时间成本的权衡五、性能与资源占用六、推荐新手下载完整版建议&#xff1a; 在 CentOS…...

AI日报 - 2025年4月13日

&#x1f31f; 今日概览(60秒速览) ▎&#x1f916; AGI突破 | OpenAI CFO称AGI可能已到来 Sarah Friar透露Sam Altman认为AGI潜力尚未完全发挥&#xff0c;引发行业热议 ▎&#x1f4bc; 商业动向 | OpenAI开发新型AI工程师A-SWE 超越Copilot&#xff0c;能独立完成应用构建、…...

有哪些基于solidity的应用

&#x1f525; Solidity 常见应用分类&#xff08;附例子&#xff09; &#x1f3e6; 1. DeFi&#xff08;去中心化金融&#xff09; Solidity 的最大应用场景之一。 项目功能示例合约逻辑Uniswap去中心化交易所&#xff08;AMM&#xff09;流动性池、定价算法、swap函数Aave /…...

mybatis--多对一处理/一对多处理

多对一处理&#xff08;association&#xff09; 多个学生对一个老师 对于学生这边&#xff0c;关联&#xff1a;多个学生&#xff0c;关联一个老师[多对一] 对于老师而言&#xff0c;集合&#xff0c;一个老师有多个学生【一对多】 SQL&#xff1a; 测试环境搭建 1.导入依…...

中兴B860AV3.2-U-晶晨S905L3B芯片-安卓9.0-2+8G-线刷固件包

中兴B860AV3.1-U&#xff0f;B860AV3.2-U--晶晨S905L3B芯片-安卓9.0-28G-线刷固件包 线刷方法&#xff1a;&#xff08;新手参考借鉴一下&#xff09; 1、准备好一根双公头USB线刷刷机线&#xff0c;长度30-50CM长度最佳&#xff0c;同时准备一台电脑&#xff1b; 2、电脑上安…...

资源分配不均,如何优化

优化资源分配需要关注资源需求评估精准性、资源调度合理性、实时监控与反馈机制、沟通协调的高效性以及持续改进的管理理念。其中&#xff0c;资源需求评估精准性最为关键。精准的资源需求评估意味着对项目各阶段所需资源的准确把控&#xff0c;这能有效防止资源过剩或短缺现象…...

Kimi-VL 解读:高效 MoE 视觉语言模型VLM,兼顾长上下文与高分辨率

写在前面:一起读多模态大模型Kimi-VL Moonshot AI 推出了 Kimi-VL,一个高效的、开源的、基于混合专家(MoE)架构的视觉语言模型。Kimi-VL 旨在解决上述痛点,它具备以下几个核心特点: 高效 MoE 架构:语言解码器采用 MoE 架构,在保持强大能力的同时,显著降低了推理时的激…...

2024团体程序设计天梯赛L3-1 夺宝大赛

L3-037 夺宝大赛 分数 30 作者 陈越 单位 浙江大学 夺宝大赛的地图是一个由 nm 个方格子组成的长方形&#xff0c;主办方在地图上标明了所有障碍、以及大本营宝藏的位置。参赛的队伍一开始被随机投放在地图的各个方格里&#xff0c;同时开始向大本营进发。所有参赛队从一个方格…...

SpringBoot DevTools:开发工具与热部署机制

文章目录 引言一、Spring Boot DevTools概述二、自动重启机制2.1 工作原理2.2 自定义重启触发器 三、LiveReload支持3.1 浏览器自动刷新3.2 与前端框架集成 四、属性默认值调整4.1 缓存配置4.2 日志配置 五、远程开发支持5.1 配置远程应用5.2 使用远程客户端 总结 引言 在Java…...

PyCharm 开发工具 修改字体大小及使用滚轮没有反应

PyCharm 开发工具 修改字体大小及使用滚轮没有反应 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是Python基础语法。前后每一小节的内容是有学习/理解关联性&#xff0c;希望对您有用~ PyCharm 开发工具 修改字体大小及…...

小刚说C语言刷题——每日一题东方博宜1000熟悉OJ环境

1.题目描述 2.参考代码(C语言版&#xff09; #include <stdio.h> int main(void) { //定义两个整型变量num1和num2 int num1,num2; int sum;//定义两个数的和sum //下面语句表示输入两个数字 scanf("%d%d",&num1,&num2); sumnum1num…...

Ubuntu安装Docker容器,通过Tomcat部署项目

温馨提示&#xff1a;本教程不是最完美的&#xff0c;只能说是填鸭式教育&#xff0c;仅仅让你快速部署Docker的tomcat项目。 *******命令行需要一行一行操作哟&#xff01;&#xff01;&#xff01;******* 一、检查Ubuntu本地的Tomcat能发正常打开项目 1.1 检查本地tomcat是…...

ubuntu22.04安装zabbix7.0

一、安装repository wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.0ubuntu24.04_all.deb dpkg -i zabbix-release_latest_7.0ubuntu24.04_all.deb apt update二、安装Zabbix server&#xff0c;Web前端&#xff0c;ag…...

AIGC工具平台-建筑平面图3D渲染

本模块是一款智能化的建筑设计辅助工具&#xff0c;可将任意房屋平面设计图快速转换为高品质3D渲染效果图&#xff0c;让建筑设计更加直观、高效。用户无需复杂的3D建模操作&#xff0c;仅需上传房屋平面图&#xff0c;系统即可一键生成符合实际尺度的3D渲染效果&#xff0c;精…...

OpenGL学习笔记(立方体贴图、高级数据、高级GLSL)

目录 立方体贴图天空盒环境映射斯涅尔定律&#xff08;Snells Law&#xff09;菲涅尔效应&#xff08;Fresnel Effect&#xff09;动态环境贴图 高级数据分批顶点属性复制缓冲 高级GLSL顶点着色器变量片段着色器变量接口块Uniform缓冲对象Uniform块布局使用Uniform缓冲测试 Git…...

嵌入式进阶:如何选择合适的开发平台?

随着现代工业、物联网以及人工智能技术的迅速发展&#xff0c;嵌入式系统已经由简单的控制器向复杂的高性能系统迈进。从传统家电到智能机器人、从自动驾驶汽车到工业自动化&#xff0c;每一项应用都对嵌入式系统的响应速度、运行稳定性和能耗管理提出了更高要求。在这种背景下…...

CVPR‘25 SOTA——GoalFlow论文精读

1&#xff09;第一遍___粗读 Q: 这篇论文试图解决什么问题&#xff1f; A: 这篇论文提出了一个名为 GoalFlow 的端到端自动驾驶方法&#xff0c;旨在解决自动驾驶场景中高质量多模态轨迹生成的问题。具体而言&#xff0c;它试图解决以下问题&#xff1a; 轨迹选择的复杂性&am…...

vue3 onMounted 使用方法和注意事项

基础用法 / 语法糖写法 <script> import { onMounted } from vue;// 选项式 API 写法 export default {setup() {onMounted(() > {console.log(组件已挂载);});} } </script><script setup> onMounted(() > {console.log(组件已挂载); }); </scrip…...

【ubuntu】linux开机自启动

目录 开机自启动&#xff1a; /etc/rc.loacl system V 使用/etc/rc*.d/系统运行优先级 遇到的问题&#xff1a; 1. Linux 系统启动阶段概述 方法1&#xff1a;/etc/rc5.d/ 脚本延时日志 方法二&#xff1a;使用 udev 规则来触发脚本执行 开机自启动&#xff1a; /etc/…...

OpenCV day2

Matplotlib相关知识 Matplotlib相关操作&#xff1a; import numpy as np from matplotlib import pyplot as pltx np.linspace(0, 2 * np.pi, 100) y1 np.sin(x) y2 np.cos(x)# 使用红色虚线&#xff0c;圆点标记&#xff0c;线宽1.5&#xff0c;标记大小为6绘制sin plt.p…...

OpenCV 图形API(31)图像滤波-----3x3 腐蚀操作函数erode3x3()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用3x3矩形结构元素腐蚀图像。 该函数通过使用中心作为锚点的3x3矩形结构元素来腐蚀源图像。腐蚀操作可以应用多次&#xff08;迭代&#xff0…...

机器学习概述自用笔记(李宏毅)

机器学习概述 机器学习即找一个复杂的人类写不出来的函数&#xff0c;把输入&#xff08;向量&#xff0c;矩阵&#xff0c;序列&#xff09;转换为输出。 regression&#xff1a;输出是一个数值&#xff08;预测PM2.5的数值&#xff09; classification&#xff1a;选择设置…...

大数据面试问答-Spark

1. Spark 1.1 Spark定位 "Apache Spark是一个基于内存的分布式计算框架&#xff0c;旨在解决Hadoop MapReduce在迭代计算和实时处理上的性能瓶颈。 1.2 核心架构 Spark架构中有三个关键角色&#xff1a; Driver&#xff1a;解析代码生成DAG&#xff0c;协调任务调度&a…...

UE5 设置父物体和解除父子关系(移除子物体)

文章目录 设置父物体解除父子关系 Acotor类似于untiy的objecttransfrom&#xff0c;可以用来进行父子操作 设置父物体 Actor attach to Actor节点 解除父子关系 Detach From Actor...

Git - 怎么把当前修改追加到前面某个commit中

怎么把当前修改追加到前面某个commit中 git log commit b7cb11b53388d410d07e3b3084c67274cee4cdad (HEAD -> hotfix/task-108344, origin_dbackup/hotfix/task-108344) Author: aaa <aaammm.com> Date: Thu Mar 27 15:08:32 2025 0800Fix #108344: add bbbcommit …...

【HFP】蓝牙 HFP 协议状态通知机制研究

目录 一、状态通知体系架构 1.1 核心功能矩阵 1.2 三层控制体系 1.3 角色分工 1.4 协议栈层级 二、核心AT命令解析 2.1 ATCMER&#xff1a;指示器状态报告控制 2.2 ATBIA&#xff1a;指示器激活控制 2.3 CIEV&#xff1a;未请求结果码 三、关键功能实现机制 3.1 注册…...

unity100天学习计划

以下是一个为期100天的Unity学习大纲,涵盖从零基础到独立开发完整游戏的全流程,结合理论、实践和项目实战,每天学习2-3小时: 第一阶段:基础奠基(Day 1-20) 目标:掌握Unity引擎基础与C#编程 Day 1-5:引擎入门 安装Unity Hub和Unity Editor(LTS版本)熟悉Unity界面:S…...