方法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;
}

 #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=; //从第一个位置上获取到数据包总长度
memcpy(&packetLength, data, sizeof(int32_t)); //指针后移
current+=sizeof(int32_t); //Message名字的长度
int protoNameLength=; //从第二个位置上获取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();
}
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 -;
} //将数据包总长度放在第一个位置
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();
t.set_time(); person person;
person.set_age();
person.set_userid();
person.set_name("irons"); char tmp[*];
ProtoMessageSender::sendMessageToBuffer(t, tmp, sizeof(tmp));
msghandle.handle(tmp); ProtoMessageSender::sendMessageToBuffer(person, tmp, sizeof(tmp));
msghandle.handle(tmp); cin.get();
return ;
}

方法2:

http://my.oschina.net/cxh3905/blog/159122

比较:

方法1把每种消息注册到链表中,当有消息来时,迭代处理,每个消息对应一个回调函数。

方法2只有1种消息,里面有个成员msg type,根据这个type做相应的处理。

前者更直观,结构清晰,每个消息占用空间合理,但效率地下。

后者效率更高,但所有数据混杂在一起,代码阅读性差。

protobuf 数据解析的2种方法的更多相关文章

  1. IOS - JSON数据解析 小3种方法

    [manager GET:serverURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject ...

  2. Android数据存储的五种方法汇总

    本文介绍Android中的5种数据存储方式. 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 ...

  3. python实现XML解析的三种方法

    python实现XML解析的三种方法 三种方法:一是xml.dom.*模块,它是W3C DOM API的实现,若需要处理DOM API则该模块很适合:二是xml.sax.*模块,它是SAX API的实 ...

  4. Android之数据存储的五种方法

    1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...

  5. 解析Xml四种方法

    关键字:Java解析xml.解析xml四种方法.DOM.SAX.JDOM.DOM4j.XPath [引言] 目前在Java中用于解析XML的技术很多,主流的有DOM.SAX.JDOM.DOM4j,下文 ...

  6. IOS开发中数据持久化的几种方法--NSUserDefaults

    IOS开发中数据持久化的几种方法--NSUserDefaults IOS 开发中,经常会遇到需要把一些数据保存在本地的情况,那么这个时候我们有以下几种可以选择的方案: 一.使用NSUserDefaul ...

  7. oracle rename数据文件的两种方法

    oracle rename数据文件的两种方法 2012-12-11 20:44 10925人阅读 评论(0) 收藏 举报  分类: oracle(98)  版权声明:本文为博主原创文章,未经博主允许不 ...

  8. 三、用Delphi10.3 创建一条JSON数据的第三种方法,非常简洁的写法

    一.用Delphi10.3构造一个JSON数据的第三种方法,并格式化输出,代码如下: uses // System.JSON, System.JSON.Types, System.JSON.Write ...

  9. XML解析的二种方法之dom解析

    XML解析的二种方法:dom解析和sax解析 文件大小      存储位置          读取速度 dom解析     小文件      放在内存中              快 sax解析   ...

随机推荐

  1. Makefile-入门与进阶【转】

    from:here 一.入门 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的 ...

  2. php注意事项2

    1.不要使用相对路径 常常会看到: require_once('../../lib/some_class.php'); 该方法有很多缺点: 它首先查找指定的php包含路径, 然后查找当前目录. 因此会 ...

  3. 用substr()截取中文出现乱码的解决方法

    截取中文字符串时出现乱码(使用substr()函数) 程序一:PHP截取中文字符串方法 function msubstr($str, $start, $len) {    $tmpstr = &quo ...

  4. angular中的代码执行顺序和$scope.$digest();

    angular中,在一个controller里$scope.whatever=function(){...} ,这样写只是在这个scope作用域里定义了一个函数,如果要执行的话还得在这个control ...

  5. ToolStrip添加自定义的DateTimePicker

    直接新建一个类,代码如下: [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All), DefaultEven ...

  6. MVP 个人理解2

    根据我的理解,画了个图 这次又看了下 较复杂点的例子. 往往一个项目有多个部份,我们可以按功能分成几个activity, 每个activity有自己的view和数据model,因此也有自己的逻辑 pr ...

  7. eclipse改变theme

    https://github.com/eclipse-color-theme/eclipse-color-theme.git https://github.com/eclipse-color-them ...

  8. 贪心算法 hdu 1009

    1.因为要排序只派j[i]/f[i],不能知道f[i]和j[i]各自排序后的顺序,因此要用到结构体 2.用sort(ware,ware+n,cmp) cmp 为俩个数组的元素比较大小的布尔值 #inc ...

  9. Maven引入本地jar包

    <dependency> <groupId>${gorup}</groupId> <artifactId>${artifact}</artifac ...

  10. DOM创建和删除节点、HTML DOM常用对象[转]

    创建和删除节点:——核心DOM   1. 创建单个元素节点:3步:      1. 创建空元素节点对象:         var elem=document.createElement("标 ...