Protobuf编码规则详解

Protobuf编码规则详解

  • 1 Message 结构
    • 1.1 tag
      • 1.1.1 字段编号(field_num)
      • 1.1.2 传输类型(wire_type)
    • 1.2 字段顺序
    • 1.3 默认值
  • 2 编码
    • 2.1 Varint编码
    • 2.1.1 Varint编码过程
      • 2.1.2解码过程
      • 2.1.3 存储
      • 2.1.4 小结
      • 2.2 有符号整数(sint32和sint64)编码的问题与zigzag优化
  • 3 编码实践
    • 3.1测试数据
    • 3.2 write_type=0 编码
      • 3.2.1 int32, int64, uint32, uint64 编码
      • 3.2.2 sint32 sint64 编码
      • 3.2.3 enum 编码
      • 3.2.4 bool编码
    • 3.3 write_type=5 编码
      • 3.3.1 float 编码
      • 3.3.2 fixed32编码
      • 3.3.3 sfixed32编码
    • 3.3 write_type=1 编码
      • 3.3.1 double编码
      • 3.3.2 fixed64编码
      • 3.3.3 sfixed64编码
    • 3.4 write_type=2 编码
      • 3.4.1 string编码
      • 3.4.2 repeated [packed] 原始数字类型 编码
      • 3.4.3 嵌套Message编码
      • 3.4.2 repeated Message
      • 3.4.2 optional 不设置
  • 4 使用建议

1 Message 结构

Message由一系列field组成,每个字段都使用TLV(Tag-Length-Value)结构形式。每个字段都有一个 tag 值,length 表示 value 数据编码后的长度,length 不是必须的,对于固定长度的和使用Varint编码的 value,是没有 length 的。value 是数据本身的内容。
在这里插入图片描述

1.1 tag

  • tag 有 field_number 和 wire_type 两部分组成,组成格式:field_num << 3 | wire_type
  • tag使用Varint编码
  • tag是要占空间的,如果tag>16时,KEY的编码就会占用2个字节了

结构如下图
在这里插入图片描述

1.1.1 字段编号(field_num)

就是.proto文件中定义的字段编号

1.1.2 传输类型(wire_type)

每个字段都有一个对应的字段(传输)类型,如下表:

TypeMeaningUsed ForStructurevalue的字节序value编码格式Length
0Varintint32, int64, uint32, uint64, sint32, sint64, bool, enumTag-Value小端字节序Varint编码变长 无Length值
164-bitfixed64, sfixed64, doubleTag-Value小端字节序非Varint编码固定8字节
2Length-delimitedstring, bytes, embedded messages, packed repeated fieldsTag-Length-Value变长,有Length值
3Start groupgroups (deprecated)
4End groupgroups (deprecated)
532-bitfixed32, sfixed32, floatTag-Value小端字节序非Varint编码固定4字节
  • 消息的二进制格式只使用消息字段的字段编号(field_num)和write_type(根据proto文件定义的类型对应而来)作为Tag的一部分,字段名和声名类型只能在解析端通过引用参考消息类型的定义(即.proto文件)才能确定。
  • 解码的时候解码程序(解码器)读入二进制的字节流,解析出每一个field;如果解码过程中遇到识别不出来的filed_num就直接跳过。这样的机制保证了即使该消息(message)添加了新的字段,也不会影响旧的编/解码程序正常工作。

1.2 字段顺序

字段编号可以在 .proto 文件中以任何顺序使用,编码 / 解码与字段顺序无关。
序列化 message 时,对于如何写入其已知字段或未知字段没有保证的顺序。解析消息不能认为filed_num=1 的消息一定在最前。

1.3 默认值

编码时如果没有对字段设置值,protobuf就不会把该字段编码到消息中。
解析数据时,如果编码的消息不包含特定的字段,则解析将对象中的相应字段将设置为该字段的默认值
不同类型的默认值不同,具体如下:

  • 对于字符串,默认值为null
  • 对于字节,默认值为空字节
  • 对于bool,默认值为false
  • 对于数字类型,默认值为零
  • 对于枚举,默认值是第一个定义的枚举值,该值必须为0。
  • repeated字段默认值是空列表
  • message字段的默认值为空对象

2 编码

2.1 Varint编码

Varint是一种将一个整数序列化为一个或者多个Byte的方法。越小的整数,使用的Bytes越少。Varint规则如下

  • 每个Byte的最高位是标志位(msb, most significant bit)。如果值为1,表示该Bytes后面还有其他Byte;如果该位为0,表示该Byte是最后一个Byte。
  • 每个Byte的低7位是用来存数值的位。
  • Varint方法使用小端字节序(低位在前编码),通常都是大端字节序(高位在前)

2.1.1 Varint编码过程

步骤/值(10进制)65128
1大端字节序二进制(低位在后/右)100000110000000
27位一分隔 (从低开始计数分隔)10000010000001,0000000
3补标志位01000001,后边高位没1了,标志位补000000001(后边高位没1了,标志位补0),10000000(后边高位有1标志位补1)
4翻转变为小端字节序(低位在前/左)0100000110000000 00000001

2.1.2解码过程

Varints 的解码就是对编码的逆操作

10进制数字65128
1pb编码值(小端字节序,低位在前/左),从低位(左)8位一分格0100000110000000 00000001
2去补标志位(最高位)10000010000000 0000001
3翻转为大端字节序(低位在后/右)10000010000001 0000000

2.1.3 存储

一个字节的 Varints 编码有 7 位可以存储数据(最高位为 msb),则可以传输 [ 0 , 2^7 -1] 以此类推,两个字节就是 [ 2 ^7 , 2^14 − 1 ]

2.1.4 小结

Varint 确实是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。比如对于 int32 类型的数字,一般需要 4 个字节来表示。但是采用 Varints,对于很小的 int32 类型的数字,则可以用 1 个字节来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个字节来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。如果确定传输大的数字,可以考虑fixed32/fixed64 类型

2.2 有符号整数(sint32和sint64)编码的问题与zigzag优化

protocol buffer中 write_type=0 的都使用Varint编码。当数值为负数时,有符号整型(sint32, sint64)和标准整型(int32, int64)有一个重要的差别。如果使用 int32 或 int64 存储负数,那么 Varints 编码后的结果一定是 10 个字节(int32 类型的负数也是占用10个字节)。而如果使用 sint32 或 sint64 存储负数,则会使用效率更高的 ZigZag 编码。
为此 Protobuf 定义了 sint32 和 sint64 这种类型,采用 ZigZag 编码。将所有整数映射成无符号整数,然后再采用 Varints 编码方式编码,这样绝对值小的整数,编码后也会有一个较小的 varint 编码值。ZigZag 映射函数为:
Zigzag(n) = (n << 1) ^ (n >> 31), n 为 sint32 时
Zigzag(n) = (n << 1) ^ (n >> 63), n 为 sint64 时
或简单理解:
正数 Zigzag(n) =2n
负数 Zigzag(n) =2
abs(n)-1

映射结果如下:

Signed OriginalEncoded As
00
-11
12
-23
24
-35
21474836474294967294
-21474836484294967295

3 编码实践

3.1测试数据

message S2
{optional int32 s2_1 = 1;optional string s2_2 = 2 ;
}enum E1 
{E1_0 = 0;E1_1 = 1;E1_3 = 3;E1_5 = 5;
}message  S3
{optional int32 s3_1 = 1;      //设置为0x88optional int32 s3_2 = 2;      //设置为0x8888optional uint32 s3_3 = 3;     //设置为0xE8E8E8optional uint32 s3_4 = 4;     //设置为0xE8E8E8E8optional int64 s3_5 = 5;      //设置为0x8888optional int64 s3_6 = 6;      //设置为0xE8E8E8E8optional uint64 s3_7 = 7;     //设置为0xE8E8E8E8optional uint64 s3_8 = 8;     //设置为0xE8E8E8E8E8E8E8E8optional sint32 s3_9 = 9;     //设置为0x8888optional sint32 s3_10 = 10;   //设置为-0x8888optional sint64 s3_64 = 64;   //注意这个tag id  设置为0xE8E8E8E8optional sint64 s3_65 = 65;   //注意这个tag id  设置为-0xE8E8E8E8optional E1 s3_11 = 11;       //设置为E1_5optional bool s3_12 = 12;     //设置为trueoptional float s3_13 = 13;    //设置 float,设置为88.888optional fixed32 s3_14 = 14;  //设置为 0x8888optional sfixed32 s3_15 = 15; //设置为 -0x8888optional double s3_16 = 16;   //设置 double,设置为8888.8888optional fixed64 s3_17 = 17;  //设置为 0x8888888888optional sfixed64 s3_18 = 18; //设置为 -0x8888888888optional string s3_19 = 19;   //设置为 "I love you,C++!"optional bytes s3_20 = 20;    //设置为 "I hate you,C++!"repeated int32 s3_21 = 21 [packed = false];    //设置为3, 270, and 86942, 用google文档的例子repeated int32 s3_22 = 22 [packed = true]; //设置为3, 270, and 86942repeated string s3_23 = 23;   //设置为"love","hate","C++"optional S2 s3_24 = 24;       //设置为 0x1,"love"repeated S2 s3_25 = 25;       //设置为 0x16,"love"  and 0x16,"hate"repeated fixed32 s3_26 = 26 [packed = false];  //设置为1,2,3optional int32 s3_27 = 27;    //不设置
}
分类说明定义FieldNumWriteType编码后(16进制)
VALUE用VARINT表示optional int32100x88 08 88 01
optional int32200x888810 88 91 02
optional uint32300xE8E8E818 e8 d1 a3 07
optional uint32400xE8E8E8E820 e8 d1 a3 c7 0e
optional int64500x888828 88 91 02
optional int64600xE8E8E8E830 e8 d1 a3 c7 0e
optional int64700xE8E8E8E838 e8 d1 a3 c7 0e
optional int64800xE8E8E8E8E8E8E8E840 e8 d1 a3 c7 8e 9d ba f4 e8 01
optional sint32900x888848 90 a2 04
optional sint32100-0x888850 8f a2 04
optional E1(enum)110E1_558 05
optional bool120true60 01
VALUE固定4个字节
FIXED32(5)
optional float13588.8886d a8 c6 b1 42
optional fixed321450x888875 88 88 00 00
optional sfixed321550x88887d 88 88 00 00
VALUE固定8个字节
FIXED64(1)
optional double1618888.888881 01 58 ca 32 c4 71 5c c1 40
optional fixed321710x888888888889 01 88 88 88 88 88 00 00 00
optional sfixed32181-0x888888888891 01 78 77 77 77 77 ff ff ff
string, bytes
embedded messages
packed repeated fields
LENGTH_DELIMITED(2)
optional string192"I love you,C++!"9a 01 of 49 20 6c 6f 76 65 20 79 6f 75 2c 43 2b 2b 21
optional bytes202"I love you,C++!"9a 01 of 49 20 6c 6f 76 65 20 79 6f 75 2c 43 2b 2b 21
optional repeated int32
[packed=false]
210 3,270,86942a8 01 03
a8 01 8e 02
a8 01 9e a7 05
optional repeated int32
[packed=true]
2223,270,86942b2 01 06 03 8e 02 9e a7 05
optional repeated string232"love","hate","C++"ba 01 04 6c 6f 76 65
ba 01 04 68 61 74 65
ba 01 03 43 2b 2b
optional S2(message)2420x1,"love" c2 01 08 08 01 12 04 6c 6f 76 65
repeated S2252S2{0x16,"love"} ,S2{0x16,"hate"} ca 01 08 08 16 12 04 6c 6f 76 65
ca 01 08 08 16 12 04 68 61 74 65
repeated fixed32[packed=false]2651,2,3d5 0101 00 00 00
d5 0102 00 00 00
d5 0103 00 00 00
可选没有设置optional int3227.没有设置没有数据

所有tag 转换过程都一样:值->二进制->分组->加标志位->翻转->转16进制

3.2 write_type=0 编码

Filed 为Tag-Value结构,没有Length,
Tag,Value 都采用 Varint编码(小端字节序)

3.2.1 int32, int64, uint32, uint64 编码

这四种类型的值直接对其做Varint编码

转换过程:值->二进制->分组->加标志位->翻转->转16进制

  • s3_1
    • tag :1<<3|0-> 0001000-> 0000 1000-> 0000 1000-> 0000 1000->->0x08
    • value: 0x88-> 10001000->000 0001,000 1000->0000 0001,1000 1000->1000 1000 ,0000 0001->88 01
  • s3_2
    • tag :2<<3|0->00010000->001 0000->0001 0000->0001 0000->10
    • value: 0x8888->1000100010001000->000 0010 ,001 0001 ,000 1000->0000 0010 ,1001 0001 ,1000 1000->1000 1000,1001 0001,0000 0010 ->88,91,02
  • s3_3
    • tag :3<<3|0->00011000->001 1000->0001 1000->0001 1000->18
    • value: 0xE8E8E8->111010001110100011101000->000 0111,010 0011 ,101 0001 ,110 1000->0000 0111,1010 0011 ,1101 0001 ,1110 1000->1110 1000,1101 0001,1010 0011,0000 0111-> E8 D1 A3 07
  • s3_4
    • tag :4<<3|0->00100000->010 0000->0010 0000->0010 0000->20
    • value:0xE8E8E8E8->000 1110,100 0111,010 0011,101 0001 ,110 1000->0000 1110,1100 0111,1010 0011,1101 0001 ,1110 1000->1110 1000,1101 0001,1010 0011,1100 0111,0000 1110->E8 D1 A3 C7 0E

3.2.2 sint32 sint64 编码

sint32 sint64 需要首先做一个zigzag 转化,转化后对值做Varint编码

tag 转换过程:值->二进制->分组->加标志位->翻转->转16进制
value转换过程:值->zigzag 转化->二进制->分组->加标志位->翻转->转16进制

  • s3_9
    • tag: 9<<3|0= 01001000-> 100 1000->0100 1000->0100 1000->48
    • value 0x8888-> 0x11110->00010001000100010000->000 0100,010 0010,001 0000->0000 0100,1010 0010,1001 0000->1001 0000 ,1010 0010,0000 0100->90 A2 04
  • s3_10
    • tag: 10<<3|0=01010000->101 0000->0101 0000->0101 0000->50
    • value 0x8888-> 0x1110F->00010001000100001111->000 0100,010 0010,000 1111->0000 0100,1010 0010,1000 1111->1000 1111,1000 1111,1010 0010,0000 0100->8F 8F A2 04

3.2.3 enum 编码

enum 是对其对应的数值做Varint编码

tag 转换过程:值->二进制->分组->加标志位->翻转->转16进制
value转换过程:值->对应数值->二进制->分组->加标志位->翻转->转16进制

  • s3_11
    • tag: 11<<3|0= 01011000-> 101 1000->0101 1000->0101 1000->58
    • value E1_5->0x5->0101-> 000 0101->0000 0101->0000 0101->05

3.2.4 bool编码

**bool,是对其对应的数值做Varint编码 ,true:1,false:0 **

value转换过程:值->对应数值->二进制->分组->加标志位->翻转->转16进制

  • s3_12
    • value true->0x1->0001-> 000 0001->0000 0001->0000 0001->01
    • value false->0x0->0000-> 000 0000->0000 0000->0000 0000->00

3.3 write_type=5 编码

Filed 为Tag-Value结构,没有Length,
Tag,采用 Varint编码(小端字节序)
Value 长度为固定定4个字节,小端字节序(非Varint编码),编码过程只是转成小端字节序即可

3.3.1 float 编码

**

编码过程只是转成小端字节序即可非Varint编码),固定长度4字节
**

  • s3_13
    • tag:13<<3|5->01101101-> 0110 1101 -> 0110 1101-> 0110 1101 ->6D
    • value:88.888f->1000010101100011100011010101000->100 0010,1011 0001,1100 0110 ,1010 1000->1010 1000,1100 0110,1011 0001,100 0010->A8 C6 B1 42

3.3.2 fixed32编码

这个用于处理32位整形的数值 和int32的区别就是

  • fixed32 长度为固定定4个字节,小端字节序(非Varint编码
  • int32 变长,小端字节序(Varint编码
  • s3_14
    • value:0x8888>1000100010001000->0000 0000 0000 0000 1000 1000 1000 1000->1000 1000 1000 1000 0000 0000 0000 0000->88 88 00 00

3.3.3 sfixed32编码

和fixed32 编码完全一样(不明白为什么弄了两个类型)

3.3 write_type=1 编码

Filed 为Tag-Value结构,没有Length,
Tag,采用 Varint编码(小端字节序)
Value 长度为固定定8个字节,小端字节序(非Varint编码),编码过程只是转成小端字节序即可

3.3.1 double编码

编码过程只是转成小端字节序即可(非Varint编码),固定长度8字节

3.3.2 fixed64编码

这个用于处理64位整形的数值 和int64的区别就是

  • fixed64 长度为固定定8个字节,小端字节序(非Varint编码
  • int64 变长,小端字节序(Varint编码

3.3.3 sfixed64编码

和fixed64编码完全一样(不明白为什么弄了两个类型)

3.4 write_type=2 编码

消息结构
在这里插入图片描述

Field含有Length

3.4.1 string编码

字段类型为 string 类型,字段值采用 UTF-8 编码,value 编码为正常字符串编码

  • s3_19
    • tag:19<<3|2-> 10011010->1 ,001 1010->0000 0001 ,1001 1010->1001 1010,0000 0001->9A 01
    • length: 15->1111->0f
    • value 正常字符串编码

3.4.2 repeated [packed] 原始数字类型 编码

  • repeated字段, proto2 默认 [packed=false],proto3中 默认 [packed=true]
  • 只有原始数字类型(使用varint,32位或64位)的repeated 字段才可以声明为 [packed=true]。
  • [packed=false] 时,编码后的 message 有一个或者多个包含相同tag(filed_num 和 **write_type 为对应的数值类型write_type**)的 field。这些 filed 不需要连续的出现。他们可能与其他的字段交错出现。尽管它们是无序的,但是在解析后它们是需要有序的。
  • [packed=true] 的repeated 字段所有的元素会被打包到单一一个 field 对中,且它的 wire_type=2,长度为所有数值编码后的长度之和。value编码按其定义类型的write_type编码,无缝排列到一起。
    在这里插入图片描述
  • s3_21[packed=false] repeated int32
    • 三个值,在Message中会有三个完整的field,三个field 的tag 都相同,write_type(因值类型为int32,所以write_type=0)
    • tag: 21<<3|0->10101000->1,0101000->0000 0001,10101000->1010 1000,0000 0001->A8 01
    • value1:3->0000 0011->03
    • value2:270->000100001110-> 0 0010 ,000 1110->0000 0010 ,1000 1110->1000 1110,0000 0010->8E 02
    • value3:86942->00010101001110011110->00 0101,010 0111,001 1110->0000 0101,1010 0111,1001 1110->1001 1110,1010 0111,0000 0101->9E A7 05
  • s3_22[packed=true] repeated int32
    • 三个值放在一个字段,value紧密排列(value的编码方式 因值类型为int32,所以是varint编码),‘write_type=2’
    • tag: 22<<3|2->10110010->1,011 0010->0000 0001,1011 0010->1011 0010,0000 0001->B2 01
    • length->6->0110->06 (长度值为value 实际编码后长度)
    • value
      • 3->0000 0011->03
      • 240->8E 02
      • 86942->9E A7 05
  • s3_23 repeated string
    • 三个值,在Message中会有三个完整的field,三个field 的tag 都相同,因值类型为String,所以write_type=2,并有length

3.4.3 嵌套Message编码

嵌套Message就是value又是一个Message,外层消息存储采用 TLV 存储,外层write_type=2 ,它的 value 又是一个 TLV 存储。整个编码结构如下图所示
在这里插入图片描述
s3_24

  • 嵌套自定义类型 的write_type=2
  • tag: 24<<3|2->11000010->1,100 0010=0000 0001, 1100 0010->1100 0010,0000 0001->C2 01
  • length-> (嵌套数据编码后实际长度)8->08
  • value:
    • s2_1:
      • write_type=0
      • tag: 1<<3|0=>1000->08
      • value:0x1->0001->01
    • s2_2:
      • write_type=2
      • tag: 2<<3|2=00010010->12
      • length:4->0100->04
      • -value: 6c 6f 76 65

3.4.2 repeated Message

  • [packed=false] 只能为false
  • write_type=2
  • 消息结构如下图,repeated Message 相当于 嵌套 多个Message并且这些Tag都一样(field_num ,write_type=2 都相同)
    在这里插入图片描述

3.4.2 optional 不设置

不设置 就不会出现在Message中

4 使用建议

  • 版本兼容宝典:字段只新增,不删除,任何时候tag不要变动(即不要修改类型和field_num)
  • 如果要出现负数,不要使用int32,int64,而应该使用sint32,sint64。
  • repeated的原始数字类型(使用varint,32位或64位)的重复字段可以声明为 [packed=true ]减小占用空间,但有低版本不兼容的风险

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

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

相关文章

【docker】exec /entrypoint.sh: no such file or directory

dockerfile生成的image 报错内容&#xff1a; exec /entrypoint.sh: no such file or directory查看文件正常在此路径&#xff0c;但是就是报错没找到。 可能是因为sh文件的换行符使用了win的。

计算机的错误计算(二百零七)

摘要 利用两个数学大模型计算 arccot(0.125664e2)的值&#xff0c;结果保留16位有效数字。 实验表明&#xff0c;它们的输出中分别仅含有3位和1位正确数字。 例1. 计算 arccot(0.125664e2)的值&#xff0c;结果保留16位有效数字。 下面是与一个数学解题器的对话。 以上为与…

MCANet: 基于多模态字幕感知的大语言模型训练无关视频异常检测

目录 摘要01 引言02 相关工作2.1 视频异常检测2.2 基于视频的大语言模型&#xff08;VLLMs&#xff09; 03 方法论3.1 问题定义3.2 MCANet3.3 图像字幕分支3.4 音频字幕分支3.5 基于LLM的异常评分3.6 视频-文本分数优化 04 实验4.1 数据集和评估指标4.2 实现细节4.3 定性结果4.…

WMS仓库管理系统,Vue前端开发,Java后端技术源码(源码学习)

一、项目背景和建设目标 随着企业业务的不断扩展&#xff0c;仓库管理成为影响生产效率、成本控制及客户满意度的重要环节。为了提升仓库作业的透明度、准确性和效率&#xff0c;本方案旨在构建一套全面、高效、易用的仓库管理系统&#xff08;WMS&#xff09;。该系统将涵盖库…

【Uniapp-Vue3】创建自定义页面模板

大多数情况下我们都使用的是默认模板&#xff0c;但是默认模板是Vue2格式的&#xff0c;如果我们想要定义一个Vue3模板的页面就需要自定义。 一、我们先复制下面的模板代码&#xff08;可根据自身需要进行修改&#xff09;&#xff1a; <template><view class"…

【Go】:图片上添加水印的全面指南——从基础到高级特性

前言 在数字内容日益重要的今天&#xff0c;保护版权和标识来源变得关键。为图片添加水印有助于声明所有权、提升品牌认知度&#xff0c;并防止未经授权的使用。本文将介绍如何用Go语言实现图片水印&#xff0c;包括静态图片和带旋转、倾斜效果的文字水印&#xff0c;帮助您有…

springCloudGateWay使用总结

1、什么是网关 功能: ①身份认证、权限验证 ②服务器路由、负载均衡 ③请求限流 2、gateway搭建 2.1、创建一个空项目 2.2、引入依赖 2.3、加配置 3、断言工厂 4、过滤工厂 5、全局过滤器 6、跨域问题

【UE5 C++课程系列笔记】22——多线程基础——FRunnable和FRunnableThread

目录 1、FRunnable 1.1 概念 1.2 主要成员函数 &#xff08;1&#xff09;Init 函数 &#xff08;2&#xff09;Run 函数 &#xff08;3&#xff09;Stop 函数 &#xff08;4&#xff09;Exit 函数 2、FRunnableThread 2.1 概念 2.2 主要操作 &#xff08;1&#xff…

《图解HTTP》 学习日记

1.了解WEB以及网络基础 1.1使用HTTP协议访问WEB web页面显示:根据web浏览器地址栏中输入指定的URL,web浏览器从web服务端获取文件资源(resource)等信息&#xff0c;从而显示出web页面 1.2网络基础TCP/IP 通常使用的网络(包括 互联网)是在tcp/ip协议族的基础上运作的&#xf…

【Docker】docker compose 安装 Redis Stack

注&#xff1a;整理不易&#xff0c;请不要吝啬你的赞和收藏。 前文 Redis Stack 什么是&#xff1f; 简单来说&#xff0c;Redis Stack 是增强版的 Redis &#xff0c;它在传统的 Redis 数据库基础上增加了一些高级功能和模块&#xff0c;以支持更多的使用场景和需求。Redis…

kubesphere前端源码运行

一、下载源码 源码是react&#xff0c;下载地址是 GitHub - kubesphere/console at v3.3.2 然后直接用git下拉就可以了 下拉完成后差不多是这样一个目录结构&#xff0c;记得切分支到3.3.2 二、下载依赖 1、node & yurn 想要运行源码首先需要node&#xff0c;使用刚才…

蓝桥杯历届真题 #分布式队列 (Java,C++)

文章目录 题目解读[蓝桥杯 2024 省 Java B] 分布式队列题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 思路完整代码 题目解读 题目链接 [蓝桥杯 2024 省 Java B] 分布式队列 题目描述 小蓝最近学习了一种神奇的队列&#xff1a;分布式队列。简单来说&#x…

PySide6 Qt for Python Qt Quick参考网址

Qt QML BOOK&#xff1a; 《Qt for Python》 -Building an Application https://www.qt.io/product/qt6/qml-book/ch19-python-build-app#signals-and-slots Qt for Python&#xff1a;与C版本的差异即BUG处理&#xff08;常见的DLL文件确实的问题等&#xff09; Qt for Pyt…

如何稳定使用 O1 / O1 Pro,让“降智”现象不再困扰?

近期&#xff0c;不少朋友在使用 O1 或 O1 Pro 模型时&#xff0c;都会碰到“降智”或“忽高忽低”的智力波动&#xff0c;比如无法识图、无法生成图片、甚至回答准确度也不稳定。面对这些问题&#xff0c;你是不是也感到头疼呢&#xff1f; 为了找到更可靠的解决办法&#xf…

用户界面的UML建模11

然而&#xff0c;在用户界面方面&#xff0c;重要的是要了解《boundary》类是如何与这个异常分层结构进行关联的。 《exception》类的对象可以作为《control》类的对象。因此&#xff0c;《exception》类能够聚合《boundary》类。 参见图12&#xff0c;《exception》Database…

记录一次面试中被问到的问题 (HR面)

文章目录 一、你对公司的了解多少二、为什么对这个岗位感兴趣三、不能说的离职原因四、离职原因高情商回复五、你的核心优势是什么六、你认为你比其他面试候选人的优势是什么七、不要提及情感 一、你对公司的了解多少 准备要点&#xff1a; 在面试前&#xff0c;对公司进行充分…

前端 图片上鼠标画矩形框,标注文字,任意删除

效果&#xff1a; 页面描述&#xff1a; 对给定的几张图片&#xff0c;每张能用鼠标在图上画框&#xff0c;标注相关文字&#xff0c;框的颜色和文字内容能自定义改变&#xff0c;能删除任意画过的框。 实现思路&#xff1a; 1、对给定的这几张图片&#xff0c;用分页器绑定…

pandas系列----DataFrame简介

DataFrame是Pandas库中最常用的数据结构之一&#xff0c;它是一个类似于二维数组或表格的数据结构。DataFrame由多个列组成&#xff0c;每个列可以是不同的数据类型&#xff08;如整数、浮点数、字符串等&#xff09;。每列都有一个列标签&#xff08;column label&#xff09;…

安装完docker后,如何拉取ubuntu镜像并创建容器?

1. 先docker拉取ubuntu镜像 docker search ubuntu #搜索ubuntu 镜像 docker pull ubuntu:22.04 #拉取ubuntu 镜像 docker images #下载完成后&#xff0c;查看已经下载的镜像 docker run --name ubuntu_container -dit ubuntu:22.04 /bin/bash # docker container -l 2.…

Qt监控系统远程网络登录/请求设备列表/服务器查看实时流/回放视频/验证码请求

一、前言说明 这几个功能是近期定制的功能&#xff0c;也非常具有代表性&#xff0c;核心就是之前登录和设备信息都是在本地&#xff0c;存放在数据库中&#xff0c;数据库可以是本地或者远程的&#xff0c;现在需要改成通过网络API请求的方式&#xff0c;现在很多的服务器很强…