Protocol Buffers介绍及例子

Protocol Buffers介绍及例子

Protocol Buffers 是一种轻便高效的结构化数据存储格式,能够用于结构化数据串行化,或者说序列化。它很适合作数据存储或数据交换格式。可用于通信协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。ios

protobuf协议是以一个 .proto 后缀的文件为基础,这个文件经过结构化数据类型的形式描述了一个数据信息。c++

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而言,不一样的类型采用的编码方式也不一样,若是是整型,采用二进制表示;若是是字符,会直接原样写入文件或者字符串(不编码)。ide

公式 field_number << 3)| wire_type,若是域号大于等于16,两个字节共16位,去掉移位的3位,去掉两个字节中第一个比特位, 总共16个比特位只有16-5==11个比特位用来表示Key,因此Key的域号要小于2^11== 2048。ui

T - L - V 的数据存储方式编码

  • Tag - Length - Value,标识 - 长度 - 字段值 存储方式
  • 以 标识 - 长度 - 字段值 表示单个数据,最终将全部数据拼接成一个 字节流,从而 实现 数据存储 的功能

正式由于采用PB自身框架代码和编译器完成和独特的编码方式,才会使protobuf的序列化紧凑,效率这么高。spa

最初的目录结构:
线程

各文件内容:翻译

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.运行可执行文件

相关文章
相关标签/搜索