google protobuf初体验

最近在读别人代码的时候发现一个的东西,名字叫protobuf, 感觉挺好用的,写在这里,留个记录。那么什么是protobuf 呢?假如您在网上搜索,应该会得到类似这样的文字介绍:

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。

说的明白点,它其实是一个可以帮你生成自定义数据结构的代码,并提供了序列化该结构的方法,并且支持多语言,跨平台等一系列优点。多说无益,直接说说该怎么用它。

首先 你需要编写proto文件,在这个文件中 用简单的方法定义了你想要定义的数据结构的组成信息。比如定义一个helloworld的信息,里面包含name, password, email 这三个信息。那么你的proto文件应该是这个样子的:

package im;
message helloworld
{
  required string usrname = 1;
  required string passwd = 2;
  optional string email = 3;
}

im 说明了包的名称, helloworld 说明了 具体的结构类型。 一个比较好的习惯是认真对待 proto 文件的文件名。比如将命名规则定于如下:packageName.MessageName.proto

接下来 你需要运行一个命令来来生成该数据结构的代码

假设您的 proto 文件存放在 $SRC_DIR 下面,您也想把生成的文件放在同一个目录下,则可以使用如下命令:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/im.helloworld.proto

那么这个时候你就会在DST_DIR下面看到im.helloworld.pb.h  im.helloworld.pb.cpp

此时基本就大功告成了,你就可以在你的代码里使用关于helloworld这个数据结构的一切了。

这个工具主要比较方便的地方是它给你提供的序列化工具。可以直接将一个数据结构序列化为字符、或者从字符反序列化为数据结构。你想,这就为很多的网络程序提供了方便,在客户机在向服务端传递消息的时候可以直接将需要传递的消息用一个数据结构封装,然后用protobuf提供的序列化方法,序列化为一个字符串,然后你人为的加一个包头(包含消息的长度和消息的类型)做一次encode;在服务端接收该消息的时候根据encode的方法对包进行接收,接收完之后再用protobuf提供的反序列化方法,从字符串再次还原为具体的数据结构信息。整个过程就不需要你去造轮子去做那些繁琐的字符解析拼装的工作了,是不是很爽? 这个我认为是protobuf比较有用的地方之一,另外一个比较有用的地方是,它可以根据类型信息去create对象,比如 之前我定义的helloworld结构,假如我现在在做一个服务端的程序,我想实现这样的一个功能,在接收到helloworld消息的时候,我去执行相应的helloworld回调。当然对于helloworld的回调是在系统启动的时候加载的。这样有一个好处,实现整个系统的模块化,并且耦合度也很低。没有这个工具的话,我可能就需要在解析的时候特别的关注收到的消息类型字段,然后根据该字段去new一个相应的对象,进而调用相应的处理过程,整个过程都需要你去手写,有了protobuf,你完全不需要造轮子了。

那么怎么样根据消息的类型直接创建相应的对象呢?代码如下:

google::protobuf::Message* create_message(const std::string& type_name)
{
  google::protobuf::Message* message = NULL;
  const google::protobuf::Descriptor* descriptor =   google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name);
  if(descriptor)
  {
    const google::protobuf::Message* prototype =
      google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
    if(prototype)
    {
      message = prototype->New();
    }
  }
  return message;
}

有点设计模式里工厂模式的味道。在消息的种类不多的时候,你可以感觉不到它的好处,但在你的系统越来越庞大的时候,你自然能体会到这个小小函数的甜头。

在你知道消息类型,并根据这个工具生成消息对象的时候,接下来就该处理了,也就是dispatch。上面我有提到过,你可以注册每个消息类型的回调处理方法,通俗点讲就是你的系统里需要有一个map,这个map里存储了不同消息的处理方法,类似于:

std::map<std::string, message_callback_t>  _message_callbacks; 这样的一个容器。具体的方法如下:

void deal_message(google::protobuf::Message* msg)
{
  auto iter_map = _message_callbacks.find(msg->GetTypeName()); //得到消息的具体类型,protobuf提供的内置方法
  if(iter_map != _message_callbacks.end())
  {
    iter_map->second(msg);  //相应的回调处理
  }
  else
  {
    std::cout << "message dealer no found" << std::endl;
  }}

你看这样是不是简直帅呆了,你的系统如果用这样的方法来执行消息分发处理,整个系统将会变得很清晰,模块间耦合很低。

基于以上的思路,我简单实现了一个client和server,来示例本博文的思路,源代码地址:https://github.com/xiaopeifeng/CodeTricks/tree/master/protobuf

欢迎指正批评。

时间: 2024-12-18 14:35:56

google protobuf初体验的相关文章

Protocol Buffers(protobuf)java初体验

由于项目需要所以简单的研究了下protobuf.我也是参照网上的博客,所以大部分内容我也就不重复造轮子了.首先protobuf介绍点击这里,使用介绍点击这里,使用demo看这里.我个人的第一个例子也是参照这个demo来的,不过其中我有遇到一些问题,所以揪出来说说,也就给自己做个笔记,方便查阅. 基本的东西相信大家也了解了,直接步入主题了: 1.限定修饰符介绍 required\optional\repeated,之前给定的博客已经有这个介绍了我也不多说,这里把一些小玩儿拿出来讲讲 ①.requi

Android Studio初体验之启动AVD模拟器异常:cannot set up guest memory &#39;pc.ram&#39;

启动AVD模拟器异常:Cannot set up guest memory 'pc.ram' 错误信息: HAX is working and emulator runs in fast virt mode Cannot set up guest memory 'pc.ram': Invalid argument Error accepting connect 分析 各种查资料,没有发现网上有同样问题的,在一篇相关文章中找到类似的解决方法. 从语意看,应该是hax安装后没有启动.(不懂hax是什

VS下使用Google Protobuf完成SOCKET通信

如何在Windows环境下的VS中安装使用Google Protobuf完成SOCKET通信 出处:如何在Windows环境下的VS中安装使用Google Protobuf完成SOCKET通信 最近一段时间,由于项目的需要,接触到了Protobuf这个东东,在Linux环境下,体验了一把,感觉挺不错,很方便,且高效.是一个非常值得学习掌握和应用的数据抽象.平台无关.功能强大.…(此处省略1000字)的开源工具. Google虽然把Protobuf做成了跨平台.跨语言,但作为微软的死对头,它在re

1Python全栈之路系列之Django初体验

Python全栈之路系列之Django初体验 Django不得不说在Python中是一个非常强大的全栈框架,而且入门也比较简单,只要你学完了基本的Django知识,接着再做一两个项目,不大不小就成,然后你再去学其它的框架你会发现,在那些小而美的框架中,你学起来将非常的快,因为你在学习Django的时候就已经学习并且体验过了Web开发流程,所以会有这么一个现象出现,有些新手朋友在学习Flask.Tornado等小而美的框架时,很多概念不是很理解,比如ORM.路由等,但你学Django就不会出现这种

Xamarin.iOS开发初体验

Xamarin是一个跨平台开发框架,这一框架的特点是支持用C#开发IOS.Android.Windows Phone和Mac应用,这套框架底层是用Mono实现的. Mono是一款基于.NET框架的开源工程,包含C#语言编译器.CLR运行时和一组类库,能运行于Windows.Linux.Unix.Mac OS和Solaris.对于.NET程序员来说,Xamarin是走向安卓.iOS.Mac跨平台开发的神器,不仅能用熟悉的C#来开发,还能使用Visual Studio作为IDE.本文内容是Xamar

Android Studio 初体验

Google在I/O2013大会上公布了Android新的开发工具Android Studio,趁周末时间做了一下尝试.有须要的能够 在http://developer.android.com/sdk/installing/studio.html下载,当前版本号是V0.1.官方解释:Android Studio is a new Android development environment based on IntelliJ IDEA. Similar to Eclipse with the

屌丝就爱尝鲜头——java8初体验

Java8已经推出,让我们看看他的魅力.让我们看看他改变较大的部分. 一.java8概述 Java8是由Oracle(甲骨文)公司与2014年3月27日正式推出的.Java8同时推出有3套语言系统,分别是Java SE8.Java SE Emebbled 8.Java ME8. Java SE8较以往的系统增强的功能有: ①增强了对集合式操作语言--lambda表达式的支持,"Lambda 表达式"(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演

Java8初体验(1):lambda表达式语法

原文出处: 一冰_天锦 本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解偏差的地方,希望大家帮忙指出,我会持续修改和优化.本文是该系列的第一篇,主要介绍Java8对屌丝码农最有吸引力的一个特性—lambda表达式. java8的安装 工欲善其器必先利其器,首先安装JDK8.过程省略,大家应该都可以自己搞定.但是有一点这里强调一下(Windows系统):目前我们工作的版本一般是java 6或者java 7,所以很多人安

我是如何初体验uglifyjs压缩JS的

一.故事总有其背景 年末将至,很多闲适的时间,于是刷刷微博,接触各种纷杂的信息——美其名曰“学习”.运气不错,遇到了一个新名词,uglifyjs. 据说是用来压缩JS文件的,据说还能优化JS,据说是基于node的,还据说比Google Closure Compiler更带感,哦?激起了我的好奇心.百之谷之,哟,相关的介绍还不少.然后折腾了个把小时,基本上知道了是个怎么回事. 我觉得吧,还是有些用的,即使是不是从事node开发的人,抽个小空,share之,于是就有了本文.人总有浮躁的时候,我也不例