protobuf学习

Protobuf介绍
参考资料:https://developers.google.cn/protocol-buffers/docs/cpptutorial
https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
protobuf是一种用来序列化和回复结构体的工具。以前的使用二进制直接进行保存、发送的方式会出现一些内存布局、大小端的问题,难以扩展。xml的话,虽然对使用者友好,但是又有很大的性能损失,此外,设计xml结构比直接使用key-value要麻烦很多。

1、 编译protobuf
github下载源码 https://github.com/protocolbuffers/protobuf
./autogen.sh
如果出错的话 apt-get install这些:
autoconf
automake
ibtool
make
g++
unzip

./configure
./make
./make check
./make install(insatlled in /usr/local/lib)

2、 测试示例
新建hello.proto
syntax = “proto2”;
package lm;
message helloworld
{
required int32 id = 1; // ID
required string str = 2; // str
optional int32 opt = 3; //optional field
}
3、 编译proto文件
执行protoc address.proto --cpp_out=./
报错error while loading shared libraries: libprotobuf.so.20: cannot open shared object file: No such file or directory
因为库路径再/usr/local/lib
执行如下操作:

$sudo echo “/usr/local/lib” >> /etc/ld.so.conf
$ldconfig

再次编译,生成两个文件address.pb.h 和address.pb.cc生成一个类

4、 编写测试代码如下:
*

#include "hello.pb.h"
#include <iostream>
#include <fstream>
using namespace std; 
 int main(void) 
 { 
  lm::helloworld msg1; 
  msg1.set_id(101); 
  msg1.set_str("aaaaa"); 
  // Write the new address book back to disk. 
  fstream output("./log", ios::out | ios::trunc | ios::binary); 
  if (!msg1.SerializeToOstream(&output)) { 
      cerr << "Failed to write msg." << endl; 
      return -1; 
  } 
  return 0; 
 }

编译g++ -g -Wall -std=c++11 helloworld.cpp hello.pb.cc -lpthread -lprotobuf
编译出错,报一堆未定义的引用的问题,是库连接出错
添加库路径g++ -g -Wall -std=c++11 helloworld.cpp hello.pb.cc -lpthread -L/usr/local/lib -lprotobuf
成功
5、 运行
发现一个很诡异的bug,编译的时候必须加上-lpthread而且-lpthread必须放在最后面,否则运行的时候报错如下:

[libprotobuf FATAL google/protobuf/generated_message_util.cc:812]
CHECK failed: (scc->visit_status.load(std::memory_order_relaxed)) ==
(SCCInfoBase::kRunning): terminate called after throwing an instance
of ‘google::protobuf::FatalException’ what(): CHECK failed:
(scc->visit_status.load(std::memory_order_relaxed)) ==
(SCCInfoBase::kRunning):

已放弃 (核心已转储)
6、 读取文件的测试代码如下:

#include “hello.pb.h”
#include
#include using namespace std;

int main(void) { lm::helloworld msg1; fstream input("./log",
ios::in|ios::binary); if(!msg1.ParseFromIstream(&input)) {
cerr<<“Failed to parse hello”<<endl; return -1; } cout<< “id:
“<<msg1.id()<<”\n”<<msg1.str()<<endl; return 0; }

protobuf的语法
1、 syntax字段标识proto2和proto3语法
2、 标识符
3、 每个字段都有唯一的标识符,1-15内的标识符占用一个字节, 16到2047占用两个字节。最小的标识号可以从1开始,最大到2^29 - 1, or 536,870,911。不可以使用其中的[19000-19999]( (从FieldDescriptor::kFirstReservedNumber 到 FieldDescriptor::kLastReservedNumber))
4、 字段规则
singular 一个格式良好的消息应该有0个或者1个这种字段
repeated 可以重复任意次
5、 同过编译proto文件,每一个定义的消息生成了一个对应的C++类
6、 序列化以及从序列获取函数:

bool SerializeToArray(void* data, int sizet)const; //把消息对象序列化 bool
ParseFromArray(void* data, int size);

一个结合protobuf与libevent的示例

https://github.com/Icc-o/LibeventLearn

其中的serverthree以及clientthree 其中的配置文件net_config.xml内容如下:

 <root>
	<server>
	<ip>192.168.6.128</ip>
	<port>9989</port>
	</server>
	<client>
	<ip>192.168.6.1</ip>
	</client>
<root>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值