一, protobuf的optional 數據類型序列化分析
1,optional 的protobuf的文件 格式
syntax = "proto2";
message test_proto
{
optional int32 proto1 = 1;
optional int32 proto2 = 2;
optional int32 proto3 = 3;
optional int32 proto4 = 4;
optional uint32 proto5 = 5;
optional string proto6 = 6;
optional int32 proto7 = 7;
optional int32 proto8 = 8;
}
測試程序
/***********************************************************************************************
* created: 2020-04-12
*
* author: chensong
*
* purpose: acceptor
* 我可能會遇到很多的人,聽他們講好2多的故事,我來寫成故事或編成歌,用我學來的各種樂器演奏它。
* 然後還可能在一個國家遇到一個心儀我的姑娘,她可能會被我帥氣的外表捕獲,又會被我深邃的內涵吸引,在某個下雨的夜晚,她會全身淋透然後要在我狹小的住處換身上的溼衣服。
* 3小時候後她告訴我她其實是這個國家的公主,她願意向父皇求婚。我不得已告訴她我是穿越而來的男主角,我始終要回到自己的世界。
* 然後我的身影慢慢消失,我看到她眼裏的淚水,心裏卻沒有任何痛苦,我才知道,原來我的心被丟掉了,我遊歷全世界的原因,就是要找回自己的本心。
* 於是我開始有意尋找各種各樣失去心的人,我變成一塊磚頭,一顆樹,一滴水,一朵白雲,去聽大家爲什麼會失去自己的本心。
* 我發現,剛出生的寶寶,本心還在,慢慢的,他們的本心就會消失,收到了各種黑暗之光的侵蝕。
* 從一次爭論,到嫉妒和悲憤,還有委屈和痛苦,我看到一隻只無形的手,把他們的本心扯碎,矇蔽,偷走,再也回不到主人都身邊。
* 我叫他本心獵手。他可能是和宇宙同在的級別 但是我並不害怕,我仔細回憶自己平淡的一生 尋找本心獵手的痕跡。
* 沿着自己的回憶,一個個的場景忽閃而過,最後發現,我的本心,在我寫代碼的時候,會回來。
* 安靜,淡然,代碼就是我的一切,寫代碼就是我本心迴歸的最好方式,我還沒找到本心獵手,但我相信,順着這個線索,我一定能順藤摸瓜,把他揪出來。
* ************************************************************************************************/
#include <iostream>
#include "test.pb.h"
static const char HEX[16] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f'
};
std::string get_hex_str(const void *_buf, int num)
{
std::string str;
str.reserve(num << 1);
const unsigned char* buf = (const unsigned char*)_buf;
unsigned char tmp;
for (int i = 0; i < num; ++i)
{
tmp = buf[i];
str.append(1, HEX[tmp / 16]);
str.append(1, HEX[tmp % 16]);
}
return str;
}
void test_msg()
{
test_proto msg;
msg.set_proto1(1);
msg.set_proto2(1);
msg.set_proto3(1);
msg.set_proto4(1);
msg.set_proto5(1);
msg.set_proto6("c");
msg.set_proto7(1);
msg.set_proto8(1);
std::string temp = msg.SerializeAsString();
printf("[hex=%s]\n", get_hex_str(temp.c_str(), temp.length()).c_str());
printf("temp = %s, len = %lu\n" , temp.c_str(), temp.length());
}
int main(int argc, char *argv[])
{
test_msg();
return 0;
}
運行效果圖
2. 分析protobuf序列化後hex碼(16進制)
序列化的後的hex碼
0801100118012001280132016338014001
解析:
08:標誌第一個的數據
01:第一個數據是1
10:第二個數據
01:第二個數據是1
18:第三個數據
01:第三個數據是1
20:第四個數據
01:第四個數據是1
28:第五個數據
01:第五個數據是1
32:第六個數據(這個標誌位是增加10標誌是string類型的數據)
01:第六個數據的長度1字節
63:第六個數據是’c’
38:第七個數據(int類型的數據標誌位是增加6)
01:第七個數據是1
40:第八個數據
01:第八個數據是1
總結:protobuf的序列化對改變數據類型時增加標誌位的是不同的
二, protobuf的repeated 數據類型序列化分析
1, repeated 的protobuf的文件 格式
syntax = "proto2";
message test_proto
{
optional int32 proto1 = 1;
repeated int32 proto2 = 2;
optional int32 proto3 = 3;
repeated int32 proto4 = 4;
}
測試程序
/***********************************************************************************************
* created: 2020-04-21
*
* author: chensong
*
* purpose: optional
* 我可能會遇到很多的人,聽他們講好2多的故事,我來寫成故事或編成歌,用我學來的各種樂器演奏它。
* 然後還可能在一個國家遇到一個心儀我的姑娘,她可能會被我帥氣的外表捕獲,又會被我深邃的內涵吸引,在某個下雨的夜晚,她會全身淋透然後要在我狹小的住處換身上的溼衣服。
* 3小時候後她告訴我她其實是這個國家的公主,她願意向父皇求婚。我不得已告訴她我是穿越而來的男主角,我始終要回到自己的世界。
* 然後我的身影慢慢消失,我看到她眼裏的淚水,心裏卻沒有任何痛苦,我才知道,原來我的心被丟掉了,我遊歷全世界的原因,就是要找回自己的本心。
* 於是我開始有意尋找各種各樣失去心的人,我變成一塊磚頭,一顆樹,一滴水,一朵白雲,去聽大家爲什麼會失去自己的本心。
* 我發現,剛出生的寶寶,本心還在,慢慢的,他們的本心就會消失,收到了各種黑暗之光的侵蝕。
* 從一次爭論,到嫉妒和悲憤,還有委屈和痛苦,我看到一隻只無形的手,把他們的本心扯碎,矇蔽,偷走,再也回不到主人都身邊。
* 我叫他本心獵手。他可能是和宇宙同在的級別 但是我並不害怕,我仔細回憶自己平淡的一生 尋找本心獵手的痕跡。
* 沿着自己的回憶,一個個的場景忽閃而過,最後發現,我的本心,在我寫代碼的時候,會回來。
* 安靜,淡然,代碼就是我的一切,寫代碼就是我本心迴歸的最好方式,我還沒找到本心獵手,但我相信,順着這個線索,我一定能順藤摸瓜,把他揪出來。
* ************************************************************************************************/
#include "test.pb.h"
#include <iostream>
static const char HEX[16] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f'
};
std::string get_hex_str(const void *_buf, int num)
{
std::string str;
str.reserve(num << 1);
const unsigned char* buf = (const unsigned char*)_buf;
unsigned char tmp;
for (int i = 0; i < num; ++i)
{
tmp = buf[i];
str.append(1, HEX[tmp / 16]);
str.append(1, HEX[tmp % 16]);
}
return str;
}
void test_msg()
{
test_proto msg;
msg.set_proto1(1);
for (int i = 0; i < 5; ++i)
{
msg.add_proto2(i+10);
}
msg.set_proto3(2);
for (int i = 0; i < 5; ++i)
{
msg.add_proto4(i+10);
}
std::string temp = msg.SerializeAsString();
printf("[hex=%s]\n", get_hex_str(temp.c_str(), temp.length()).c_str());
printf("temp = %s, len = %lu\n" , temp.c_str(), temp.length());
// 序列化的後的hex碼
// 0801 100a 100b 100c 100d 100e 1802 200a200b200c200d200e
//
// 解析:
//
// 08:標誌第一個的數據
// 01:第一個數據是1
// 10:第二個數據(10 這裏的 10 和地下的10相同表示是 repeated類型的數據 下面10出現次數就是repeated類型數據的個數)
// 0a:第二個數據是10
// 10:第三個數據
// 0b:第三個數據是11
// 10:第四個數據
// 0c:第四個數據是12
// 10:第五個數據
// 0d:第五個數據是13
// 10:第六個數據
// 0e:第六個數據的長度1字節
// 18:第七個數據(int類型的數據標誌位是增加6 因爲 上面的repeated 類型數據出現的5次使用 是 8 +(5 * 2) = 18)
// 01:第七個數據是2
// 20:第八個數據(20 這裏的 20 和地下的20相同表示是 repeated類型的數據 下面20出現次數就是repeated類型數據的個數)
// 0a:第八個數據是10 底下類似的
// ...........
//
// 總結:protobuf的序列化對repeated數據類型的個數是不改變標誌位的計算個數
}
int main(int argc, char *argv[])
{
test_msg();
return 0;
}
運行效果圖
2. 分析protobuf序列化後hex碼(16進制)
序列化的後的hex碼
0801 100a 100b 100c 100d 100e 1802 200a200b200c200d200e
解析:
08:標誌第一個的數據
01:第一個數據是1
10:第二個數據(10 這裏的 10 和地下的10相同表示是 repeated類型的數據 下面10出現次數就是repeated類型數據的個數)
0a:第二個數據是10
10:第三個數據
0b:第三個數據是11
10:第四個數據
0c:第四個數據是12
10:第五個數據
0d:第五個數據是13
10:第六個數據
0e:第六個數據的長度1字節
18:第七個數據(int類型的數據標誌位是增加6 因爲 上面的repeated 類型數據出現的5次使用 是 8 +(5 * 2) = 18)
01:第七個數據是2
20:第八個數據(20 這裏的 20 和地下的20相同表示是 repeated類型的數據 下面20出現次數就是repeated類型數據的個數)
0a:第八個數據是10 底下類似的
…
總結:protobuf的序列化對repeated數據類型的個數是不改變標誌位的計算個數