protobuf 数据解析的2种方法

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

 

  1 #include <string>
  2 #include <iostream>
  3 #include <assert.h>
  4 #include <stdint.h>
  5 
  6 #include "person.pb.h"
  7 #include "test.pb.h"
  8 
  9 using namespace std;
 10 
 11 class ProtoMsgHandle
 12 {
 13 public:
 14     /*  注册消息处理函数 */
 15     void    initHandles()
 16     {
 17         registerHandle(&ProtoMsgHandle::handleProtoPerson);
 18         registerHandle(&ProtoMsgHandle::handleProtoTest);
 19     }
 20 
 21     /*  处理网络消息
 22      *  data 为一个完整的数据包
 23      */
 24     void    handle(const char* data)
 25     {
 26         bool ret = false;
 27 
 28         const char * current=data;
 29 
 30         //在网络上传输的一个数据包总长度
 31         int packetLength=0;
 32 
 33         //从第一个位置上获取到数据包总长度
 34         memcpy(&packetLength, data, sizeof(int32_t));
 35 
 36         //指针后移
 37         current+=sizeof(int32_t);
 38 
 39         //Message名字的长度
 40         int protoNameLength=0;
 41 
 42         //从第二个位置上获取Message的名字的长度
 43         memcpy(&protoNameLength, current, sizeof(int32_t));
 44 
 45         //指针后移
 46         current+=sizeof(int32_t);
 47 
 48         //从第三个位置上获取Message的名字
 49         string name(current,protoNameLength);
 50 
 51         //指针后移
 52         current+=protoNameLength;
 53 
 54         //取得Message的字节数
 55         int messageSize=packetLength-(sizeof(int32_t)+sizeof(int32_t)+protoNameLength);
 56 
 57         do{
 58 
 59             msg_handle callback = m_callbacks[name];
 60 
 61             assert(callback != NULL);
 62 
 63             if(callback == NULL)
 64             {
 65                 std::cout<<"proto "<<name<<" had not register handler"<<std::endl;
 66                 break;
 67             }
 68             const ::google::protobuf::Descriptor* descriptor = m_descriptors[name];
 69             assert(descriptor != NULL);
 70             if(descriptor == NULL)
 71             {
 72                 std::cout<<"proto "<<name<<" had no descriptor"<<std::endl;
 73                 break;
 74             }
 75             const google::protobuf::Message* prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
 76             assert(prototype != NULL);
 77             if(prototype == NULL)
 78             {
 79                 std::cout<<"proto "<<name<<" had no prototype"<<std::endl;
 80                 break;
 81             }
 82             google::protobuf::Message* msg = prototype->New();
 83             ret = msg->ParseFromArray(current,messageSize);
 84             if(ret)
 85             {
 86                 (this->*callback)(msg);
 87             }
 88             else
 89             {
 90                 std::cout<<"proto "<<name<<" parse fail"<<std::endl;
 91             }
 92 
 93         }while(0);
 94     }
 95 private:
 96     void handleProtoTest(test* test)
 97     {
 98         cout <<"test->price()="<< test->price() << endl;
 99         cout << "test->userid()="<<test->userid() << endl;
100         cout << "test->time()="<<test->time() << endl;
101     }
102     void handleProtoPerson(person* person)
103     {
104         cout << "person->age()="<<person->age() << endl;
105         cout << "person->userid()="<<person->userid() << endl;
106         cout << "person->name()="<<person->name() << endl;
107     }
108 
109 private:
110 
111     typedef void (ProtoMsgHandle::*msg_handle)(::google::protobuf::Message*);
112 
113     map<string, msg_handle>                                 m_callbacks;
114 
115     map<string, const ::google::protobuf::Descriptor*>      m_descriptors;
116 
117     template<typename MSGTYPE> void registerHandle(void (ProtoMsgHandle::*callback)(MSGTYPE*))
118     {
119         const ::google::protobuf::Descriptor*des =MSGTYPE::descriptor();
120         assert(des != NULL);
121         if(des != NULL)
122         {
123             m_callbacks[des->full_name()] = (msg_handle)callback;
124             m_descriptors[des->full_name()] = des;
125         }
126     }
127 
128 
129 };
130 
131 class ProtoMessageSender
132 {
133 public:
134     /*  发送proto msg到指定缓冲区
135      *  int32_t   packetLength 数据包总长度
136      *  int32_t   messageNameLength 消息名长度
137      *  char[]    messageName 消息名
138      *  char[]    Message 消息
139      *  char*     buffer 缓冲区
140      *  int       maxLength 消息的最大长度
141      */
142     template<typename MSGTYPE> static int sendMessageToBuffer(MSGTYPE& msg, char* buffer, int maxLength){
143 
144         char * current=buffer;
145 
146         //Message的字节数
147         int messageSize=msg.ByteSize();
148 
149         //Message的名字
150         string messageName=MSGTYPE::descriptor()->full_name();
151 
152         //Message名字的长度
153         size_t messageNameLength=messageName.size();
154 
155         //消息组成 messageSize+messageNameLength+messageName+Message
156         size_t packetLength=sizeof(int32_t)+sizeof(int32_t)+messageNameLength+messageSize;
157 
158         if (packetLength>maxLength) {
159             return -1;
160         }
161 
162         //将数据包总长度放在第一个位置
163         memcpy(current, &packetLength, sizeof(int32_t));
164 
165         //指针后移
166         current+=sizeof(int32_t);
167 
168         //将Message名称长度放在第二个位置
169         memcpy(current, &messageNameLength, sizeof(int32_t));
170 
171         //指针后移
172         current+=sizeof(int32_t);
173 
174         //将协议名称放在第三个位置上
175         strcpy(current,messageName.c_str());
176 
177         //指针后移
178         current+=messageNameLength;
179 
180         //将Message放在第四个位置上
181         msg.SerializeToArray(current,messageSize);
182 
183         return (int)packetLength;
184 
185     }
186 };
187 
188 int main()
189 {
190 
191     ProtoMsgHandle msghandle;
192     msghandle.initHandles();
193 
194     test t;
195     t.set_price(100.0);
196     t.set_userid(110);
197     t.set_time(123);
198 
199     person person;
200     person.set_age(18);
201     person.set_userid(200508);
202     person.set_name("irons");
203 
204     char tmp[10*1024];
205     ProtoMessageSender::sendMessageToBuffer(t, tmp, sizeof(tmp));
206     msghandle.handle(tmp);
207 
208     ProtoMessageSender::sendMessageToBuffer(person, tmp, sizeof(tmp));
209     msghandle.handle(tmp);
210 
211     cin.get();
212     return 0;
213 }

 

方法2:

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

 

 

比较:

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

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

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

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

 

转载于:https://www.cnblogs.com/wjx0912/p/5601073.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/418383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(1978)vue之电商管理系统电商系统之为每一行数据提供单独的value

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

软工学习笔记——代码规范

上大学以来写了这几年的代码&#xff0c;却一直没怎么关注过代码规范相关的问题&#xff0c;直到软工课上讲了之后&#xff0c;才开始有所顾及。上课的时候回头看看自己写过的那些代码&#xff0c;真是丑死了&#xff0c;几个月前自己写的代码现在就已经读不懂了。 看了书上的相…

前端学习(1981)vue之电商管理系统电商系统之完成可选项的添加操作

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

ext4文件系统的delalloc选项造成单次写延迟增加的分析

最近我们的服务进程遇到kill -15后处于Z的状态&#xff0c;变为了僵尸进程&#xff0c;经过/proc/{thread_id}/stack查看其上线程的栈&#xff0c;发现是卡在了fwrite的过程中&#xff0c;而我们的系统中所有文件系统挂载参数都使用了delalloc参数&#xff0c;怀疑是这个原因&a…

前端学习(1982)vue之电商管理系统电商系统之删除参数的操作

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

前端学习(1983)vue之电商管理系统电商系统之清空表格数据

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

python 进程和线程

python中的进程、线程&#xff08;threading、multiprocessing、Queue、subprocess&#xff09; Python中的进程与线程 学习知识&#xff0c;我们不但要知其然&#xff0c;还是知其所以然。你做到了你就比别人NB。 我们先了解一下什么是进程和线程。 进程与线程的历史 我们都知…

NYU Hand Pose Dataset

http://cims.nyu.edu/~tompson/NYU_Hand_Pose_Dataset.htm#overview 转载于:https://www.cnblogs.com/guochen/p/5610681.html

前端学习(1984)vue之电商管理系统电商系统之完成静态属性

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

java实现文件在线预览

RequestMapping("/preview1") public void er(HttpServletResponse response){File file new File("G:\\桌面\\Thymeleaf3.0中文翻译文档www.java1234.com.pdf");if (file.exists()){byte[] data null;try {FileInputStream input new FileInputStream(…

Python 运维(三):使用 zipapp 将 Python 程序打包成单个可执行文件

大家好&#xff0c;我是水滴~~ 在 Python 开发中&#xff0c;我们经常需要将应用程序打包成可执行文件&#xff0c;以便在不具备 Python 环境的计算机上运行。Python 提供了多种打包工具&#xff0c;其中之一就是 zipapp。zipapp 可以将 Python 应用程序及其依赖打包成一个单独…

FreeMarker 集合遍历

freemarker list (长度,遍历,下标,嵌套,排序) 1. freemarker获取list的size &#xff1a; Java ArrayList<String> list new ArrayList<String>(); Freemaker ${list?size} 2. list的遍历&#xff1a; <#list animals as being> <tr> <td>${be…

java 返回文件的二进制字符串给前端

RequestMapping(value "/fileToStream", method RequestMethod.GET)ApiOperation("将文件转成流传给前端")public WebResponse fileToStream(HttpServletResponse response, HttpServletRequest request){ // // 自动判断下载文件类型 // response.set…

【BZOJ-3033】太鼓达人 欧拉图 + 暴搜

3033: 太鼓达人 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 204 Solved: 154[Submit][Status][Discuss]Description 七夕祭上&#xff0c;Vani牵着cl的手&#xff0c;在明亮的灯光和欢乐的气氛中愉快地穿行。这时&#xff0c;在前面忽然出现了一台太鼓达人机台&#xff…

ubuntu创建、删除文件及文件夹,强制清空回收站方法

mkdir 目录名 > 创建一个目录 rmdir 空目录名 > 删除一个空目录 rm 文件名 文件名 > 删除一个文件或多个文件 rm –rf 非空目录名 > 删除一个非空目录下的一切 touch 文件名 > 创建一个空文件 重命名文件&#xff08;夹&#xff09; / 移…

前端学习(1987)vue之电商管理系统电商系统之通过路由加载商品列表

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…

unity, 同步物体坐标一定要在LateUpdate中进行

设a为主动物体&#xff0c;b为跟随物体。 如果a,b都在同一个Update里更新坐标&#xff0c;那么两者自然是同步的。 如果a在a.Update里更新位置&#xff0c;而b在b.Update里将自己的位置更新为与a相同&#xff0c;那就会有误差。 而且即使a的运动非常缓慢平滑&#xff0c;b也会出…

前端学习(1988)vue之电商管理系统电商系统之获取商品列表

目录结构 router.js import Vue from vue import Router from vue-router import Login from ./components/Login.vue import Home from ./components/Home.vue import Welcome from ./components/Welcome.vue import Users from ./components/user/Users.vue import Right fr…