1. 程式人生 > >Protocol Buffers介紹及例子

Protocol Buffers介紹及例子

-- 多線程 方式 最終 remember mis mage tro 整型

Protocol Buffers介紹及例子

Protocol Buffers 是一種輕便高效的結構化數據存儲格式,可以用於結構化數據串行化,或者說序列化。它很適合做數據存儲或數據交換格式。可用於通訊協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。目前提供了 C++、Java、Python 三種語言的 API。

protobuf協議是以一個?.proto?後綴的文件為基礎,這個文件通過結構化數據類型的形式描述了一個數據信息。

protobuf的序列化底層原理:

you can see, each field in the message definition has a unique numbered tag. These tags are used to identify your fields in the message binary format, and should not be changed once your message type is in use. Note that tags with values in the range 1 through 15 take one byte to encode. Tags in the range 16 through 2047 take two bytes. So you should reserve the tags 1 through 15 for very frequently occurring message elements. Remember to leave some room for frequently occurring elements that might be added in the future.

翻譯為:
protobuf協議使用二進制格式表示Key字段;對value而言,不同的類型采用的編碼方式也不同,如果是整型,采用二進制表示;如果是字符,會直接原樣寫入文件或者字符串(不編碼)。

公式 field_number << 3)| wire_type,如果域號大於等於16,兩個字節共16位,去掉移位的3位,去掉兩個字節中第一個比特位, 總共16個比特位只有16-5==11個比特位用來表示Key,所以Key的域號要小於2^11== 2048。

T - L - V?的數據存儲方式

  • Tag - Length - Value,標識 - 長度 - 字段值?存儲方式
  • 以?標識 - 長度 - 字段值?表示單個數據,最終將所有數據拼接成一個?字節流,從而 實現 數據存儲 的功能

正式因為采用PB自身框架代碼和編譯器完成和獨特的編碼方式,才會使protobuf的序列化緊湊,效率這麽高。

最初的目錄結構:
技術分享圖片

各文件內容:

cat helloworld.proto

syntax = "proto2";
package lm;
message helloworld
{
    required int32 id = 1;
    required string str = 2;
    optional int32 opt=3;
}

cat main.cpp

#include <iostream>
#include <fstream>
#include "protoc_dir/helloworld.pb.h"

using namespace std;
 
void ListMsg(const lm::helloworld & msg){
    cout << msg.id()<<endl;
    cout << msg.str()<<endl;
}
 
int main(void)
{
    lm::helloworld msg1;
    lm::helloworld msg2;
    msg1.set_id(101);     //設置id
    msg1.set_str("helloworld");    //設置字符串
    {
        fstream output("./tst.log", ios::out |ios::trunc |ios::binary);
        if (!msg1.SerializeToOstream(&output)){
            cerr << "failed to serialize msg1" <<endl;
            return -1;
        }
    }
    {
        fstream input("./tst.log",ios::in|ios::binary);
        if (!msg2.ParseFromIstream(&input)){
            cerr << "failed to parse" <<endl;
            return -1;
        }
        ListMsg(msg2);
    }
    return 0;
}

1.根據.proto文件生成.cc .h文件

protoc --cpp_out=./protoc_dir/ helloworld.proto
技術分享圖片

2.編譯源代碼
g++ -std=c++11 main.cpp protoc_dir/helloworld.pb.cc -lprotobuf -lpthread -o obj_run
技術分享圖片

註意: protobuf用到了多線程, 所以一定要加上 lpthread

3.運行可執行文件
技術分享圖片

Protocol Buffers介紹及例子