protobuffer学习笔记

一、环境的安装及测试

参考博文

  • 首先需要获取安装包
  • 接着逐条输入以下指令即可
 tar -xzf protobuf-2.1.0.tar.gz 
 cd protobuf-2.1.0 
 ./configure --prefix=/usr/local/protobuf
 make 
 make check 
 make install 

./configure --prefix=/usr/local/protobuf 用于配置安装的路径

  • 2 > sudo vim /etc/profile
 添加
export PATH=$PATH:/usr/local/protobuf/bin/
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
保存执行
source /etc/profile
  • 3 > sudo vim ~/.profile
 添加
export PATH=$PATH:/usr/local/protobuf/bin/
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
保存执行
source ~/.profile
  • 4 > 配置动态链接库路径
sudo vim /etc/ld.so.conf
插入:
/usr/local/protobuf/lib
  • 5 > su #root 权限
ldconfig
  • 查看是否安装成功
    protoc --version

  • 6 > 写消息文件:msg.proto

package lm; 
message helloworld 
{ 
    required int32     id = 1;  // ID   
    required string    str = 2;  // str  
    optional int32     opt = 3;  //optional field 
}
  • 将消息文件msg.proto映射成cpp文件
protoc -I=. --cpp_out=. msg.proto
可以看到生成了
msg.pb.h 和msg.pb.cc
--objc_out
  • 7 > 写序列化消息的进程
#include "msg.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
 
int main(void) 
{ 
 
    lm::helloworld msg1; 
    msg1.set_id(101); 
    msg1.set_str("hello"); 
    fstream output("./log", ios::out | ios::trunc | ios::binary); 
 
    if (!msg1.SerializeToOstream(&output)) { 
        cerr << "Failed to write msg." << endl; 
        return -1; 
    }        
    return 0; 
}
  • 编译 write.cc
g++  msg.pb.cc write.cc -o write  `pkg-config --cflags --libs protobuf` -lpthread
  • 执行write
    ./write, 可以看到生成了log文件

  • 7> 写反序列化的进程
    reader.cc

#include "msg.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
 
void ListMsg(const lm::helloworld & msg) {  
    cout << msg.id() << endl; 
    cout << msg.str() << endl; 
} 
 
int main(int argc, char* argv[]) { 
 
    lm::helloworld msg1; 
 
    { 
        fstream input("./log", ios::in | ios::binary); 
        if (!msg1.ParseFromIstream(&input)) { 
            cerr << "Failed to parse address book." << endl; 
            return -1; 
        }       
    } 
 
    ListMsg(msg1); 
}
  • 编译:g++ msg.pb.cc reader.cc -o reader pkg-config --cflags --libs protobuf -lpthread
    执行./reader 输出 :
    101
    hello

  • 编写makefile

all: write reader
 
clean:
    rm -f write reader msg.*.cc msg.*.h *.o  log
 
proto_msg:
    protoc --cpp_out=. msg.proto
 
 
write: msg.pb.cc write.cc
    g++  msg.pb.cc write.cc -o write  `pkg-config --cflags --libs protobuf`
 
reader: msg.pb.cc reader.cc
    g++  msg.pb.cc reader.cc -o reader  `pkg-config --cflags --libs protobuf`

二、序列化分析

参考博文

例子一

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

080a 120a 6865 6c6c 6f2c 6c6f 6e6e …hello,lonn

序列化之后,每个字段之前都有一个字段的标识,如上面标成黄色的 08 ,12。

这些标识,有两个含义一个是字段序号,另一个是字段的种类。

例子二

在多一个例子
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

080a 1002 1803 2004 2a0a 6865 6c6c 6f2c 6c6f 6e6e

分析

由上面的两个例子,我们得到了两个序列化的数据

080a 120a 6865 6c6c 6f2c 6c6f 6e6e …hello,lonn
080a 1002 1803 2004 2a0a 6865 6c6c 6f2c 6c6f 6e6e

上面的黄色的数组都是用来表示一个定义好的字段的。
其中包含了field number(简写成fn)以及wire type(简写为wt)。
其中field number是proto文件中标注的该字段数字代号,而wire type表示本字段的数据归类
数据归类主要用于提醒反序列化程序如何判断本字段值占据几个字节
在这里插入图片描述

Wire Type解释数据类型
0varint变长整型(见下文)int32, int64, uint32, uint64, sint32, sint64, bool, enum
1固定8字节fixed64, sfixed64, double
2需显式告知长度(见下文)string, bytes, 嵌套类型(embedded messages),repeated字段
3(已废弃)(已废弃)
4(已废弃)(已废弃)
5固定4字节fixed32, sfixed32, float

因为wire type种类很少,为了节约字节,write type只用了3个bits来表示,而fn则使用更高位来表示。

080a 120a 6865 6c6c 6f2c 6c6f 6e6e …hello,lonn
080a 1002 1803 2004 2a0a 6865 6c6c 6f2c 6c6f 6e6e

如上面的序列化后的数据的 第一个数字标识 08。十六进制08等于二进制的0000 1000
在这里插入图片描述

  • 二进制的 第1位 最高字节。
    每个字节最高位不用来表示具体数值,只用来表示“本字节是不是这个数字的最后一个字节”。0表示最后一个字节,1表示不是最后一字节、后面还有。

  • 二进制的 第2~5位 是field number
    field number 的数字是根据proto标注的字段数据决定的”。这里是1。
    注意:field number大于15时会使用更多的位来实现表示,如下图:
    在这里插入图片描述
    在这里插入图片描述

  • 二进制的 后三位,是wire type
    wire type固定在后三位。这里是0,表示varint变长整型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值