protobuf 数据解析的2种方法
来源:互联网 发布:linux sacc 编辑:程序博客网 时间:2024/05/21 10:50
方法1:
message person
{
required int32 age = 1;
required int32 userid = 2;
optional string name = 3;
}
message test
{
required int32 time = 1;
required int32 userid = 2;
required float price = 3;
optional string desc = 4;
}
方法2:
http://my.oschina.net/cxh3905/blog/159122
比较:
方法1把每种消息注册到链表中,当有消息来时,迭代处理,每个消息对应一个回调函数。
方法2只有1种消息,里面有个成员msg type,根据这个type做相应的处理。
前者更直观,结构清晰,每个消息占用空间合理,但效率地下。
后者效率更高,但所有数据混杂在一起,代码阅读性差。
message person
{
required int32 age = 1;
required int32 userid = 2;
optional string name = 3;
}
message test
{
required int32 time = 1;
required int32 userid = 2;
required float price = 3;
optional string desc = 4;
}
#include <string>#include <iostream>#include <assert.h>#include <stdint.h>#include "person.pb.h"#include "test.pb.h"using namespace std;class ProtoMsgHandle{public: /* 注册消息处理函数 */ void initHandles() { registerHandle(&ProtoMsgHandle::handleProtoPerson); registerHandle(&ProtoMsgHandle::handleProtoTest); } /* 处理网络消息 * data 为一个完整的数据包 */ void handle(const char* data) { bool ret = false; const char * current=data; //在网络上传输的一个数据包总长度 int packetLength=0; //从第一个位置上获取到数据包总长度 memcpy(&packetLength, data, sizeof(int32_t)); //指针后移 current+=sizeof(int32_t); //Message名字的长度 int protoNameLength=0; //从第二个位置上获取Message的名字的长度 memcpy(&protoNameLength, current, sizeof(int32_t)); //指针后移 current+=sizeof(int32_t); //从第三个位置上获取Message的名字 string name(current,protoNameLength); //指针后移 current+=protoNameLength; //取得Message的字节数 int messageSize=packetLength-(sizeof(int32_t)+sizeof(int32_t)+protoNameLength); do{ msg_handle callback = m_callbacks[name]; assert(callback != NULL); if(callback == NULL) { std::cout<<"proto "<<name<<" had not register handler"<<std::endl; break; } const ::google::protobuf::Descriptor* descriptor = m_descriptors[name]; assert(descriptor != NULL); if(descriptor == NULL) { std::cout<<"proto "<<name<<" had no descriptor"<<std::endl; break; } const google::protobuf::Message* prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor); assert(prototype != NULL); if(prototype == NULL) { std::cout<<"proto "<<name<<" had no prototype"<<std::endl; break; } google::protobuf::Message* msg = prototype->New(); ret = msg->ParseFromArray(current,messageSize); if(ret) { (this->*callback)(msg); } else { std::cout<<"proto "<<name<<" parse fail"<<std::endl; } }while(0); }private: void handleProtoTest(test* test) { cout <<"test->price()="<< test->price() << endl; cout << "test->userid()="<<test->userid() << endl; cout << "test->time()="<<test->time() << endl; } void handleProtoPerson(person* person) { cout << "person->age()="<<person->age() << endl; cout << "person->userid()="<<person->userid() << endl; cout << "person->name()="<<person->name() << endl; }private: typedef void (ProtoMsgHandle::*msg_handle)(::google::protobuf::Message*); map<string, msg_handle> m_callbacks; map<string, const ::google::protobuf::Descriptor*> m_descriptors; template<typename MSGTYPE> void registerHandle(void (ProtoMsgHandle::*callback)(MSGTYPE*)) { const ::google::protobuf::Descriptor*des =MSGTYPE::descriptor(); assert(des != NULL); if(des != NULL) { m_callbacks[des->full_name()] = (msg_handle)callback; m_descriptors[des->full_name()] = des; } }};class ProtoMessageSender{public: /* 发送proto msg到指定缓冲区 * int32_t packetLength 数据包总长度 * int32_t messageNameLength 消息名长度 * char[] messageName 消息名 * char[] Message 消息 * char* buffer 缓冲区 * int maxLength 消息的最大长度 */ template<typename MSGTYPE> static int sendMessageToBuffer(MSGTYPE& msg, char* buffer, int maxLength){ char * current=buffer; //Message的字节数 int messageSize=msg.ByteSize(); //Message的名字 string messageName=MSGTYPE::descriptor()->full_name(); //Message名字的长度 size_t messageNameLength=messageName.size(); //消息组成 messageSize+messageNameLength+messageName+Message size_t packetLength=sizeof(int32_t)+sizeof(int32_t)+messageNameLength+messageSize; if (packetLength>maxLength) { return -1; } //将数据包总长度放在第一个位置 memcpy(current, &packetLength, sizeof(int32_t)); //指针后移 current+=sizeof(int32_t); //将Message名称长度放在第二个位置 memcpy(current, &messageNameLength, sizeof(int32_t)); //指针后移 current+=sizeof(int32_t); //将协议名称放在第三个位置上 strcpy(current,messageName.c_str()); //指针后移 current+=messageNameLength; //将Message放在第四个位置上 msg.SerializeToArray(current,messageSize); return (int)packetLength; }};int main(){ ProtoMsgHandle msghandle; msghandle.initHandles(); test t; t.set_price(100.0); t.set_userid(110); t.set_time(123); person person; person.set_age(18); person.set_userid(200508); person.set_name("irons"); char tmp[10*1024]; ProtoMessageSender::sendMessageToBuffer(t, tmp, sizeof(tmp)); msghandle.handle(tmp); ProtoMessageSender::sendMessageToBuffer(person, tmp, sizeof(tmp)); msghandle.handle(tmp); cin.get(); return 0;}
方法2:
http://my.oschina.net/cxh3905/blog/159122
比较:
方法1把每种消息注册到链表中,当有消息来时,迭代处理,每个消息对应一个回调函数。
方法2只有1种消息,里面有个成员msg type,根据这个type做相应的处理。
前者更直观,结构清晰,每个消息占用空间合理,但效率地下。
后者效率更高,但所有数据混杂在一起,代码阅读性差。
阅读全文
0 0
- protobuf 数据解析的2种方法
- Netty protobuf解析2-官方方法解析
- protobuf的编译方法
- 如何解析超长的protobuf
- protobuf 数据序列化和反解析
- Gson解析josn数据的2种方法
- protobuf 数据的一种封装
- Unity常见的解析数据方式XML,JSON,ProtocolBuf篇(一)Protobuf
- 解析protobuf
- ocos2dx-lua采用pbc解析protobuf 不支持message嵌套和枚举不支持整数的处理方法
- 解析配置文件数据的方法
- UIWebView 解析数据的方法
- 解析JSON数据的方法
- protobuf的ParseFromArray 解析失败的问题
- protobuf【2】Varints方法编码
- Burpsuite中protobuf数据流的解析
- LuaFramework数据传输Protobuf的解析repeated字段
- grpc+protobuf 的C++ service 实例解析
- scala 2.11.7学习笔记1之概述
- 如何用Spring AOP和Java自定义注解实现登陆鉴权
- ionic 简单应用下拉刷新 选项卡栏操作 滚动条
- 图像多尺度技术
- Oracle Database JDBC驱动下载
- protobuf 数据解析的2种方法
- CefGlue 增加对 F12 弹出 开发者工具 (devTools)的支持
- 初识lldp协议
- Day019
- 中国IT行业为何频获风投青睐?
- 数据结构
- 关于d3生成图片的一些实例
- ffmpeg首页搜索可以查到api
- 第十四周项目2