最近在读别人代码的时候发现一个的东西,名字叫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

欢迎指正批评。

google protobuf初体验的更多相关文章

  1. protobuf初体验

    概念介绍 Protocol buffers 是google公司的与语言无关.与平台无关的.可扩张的为序列化话结构数据,就像xml一样,办事更加的小巧.快速.简单.Protocol buffers 目前 ...

  2. protobuf(Protocol Buffers)java初体验

    因为项目须要所以简单的研究了下protobuf.我也是參照网上的博客,所以大部分内容我也就不反复造轮子了.首先protobuf介绍点击这里,使用介绍点击这里,使用demo看这里. 我个人的第一个样例也 ...

  3. ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...

  4. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  5. win7升win10,初体验

    跟宿舍哥们聊着聊着,聊到最近发布正式版的win10,听网上各种评论,吐槽,撒花的,想想,倒不如自己升级一下看看,反正不喜欢还可以还原.于是就开始了win10的初体验了,像之前装黑苹果双系统一样的兴奋, ...

  6. python--爬虫入门(七)urllib库初体验以及中文编码问题的探讨

    python系列均基于python3.4环境 ---------@_@? --------------------------------------------------------------- ...

  7. Java8初体验(一)lambda表达式语法

    感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解 ...

  8. node.js 初体验

    node.js 初体验 2011-10-31 22:56 by 聂微东, 174545 阅读, 118 评论, 收藏, 编辑 PS: ~ 此篇文章的进阶内容在为<Nodejs初阶之express ...

  9. YII学习,初体验 ,对YII的一些理解.

    先说点没用的: 不会选择,选择后不坚持,不断的选择.这是人生中的一个死循环,前两一直迷茫.觉得自己前进方向很不明朗.想去学的东西有很多.想学好YII,想学PYTHON 想学学hadoop什么的,又想研 ...

随机推荐

  1. GDI+中发生一般性错误的解决办法

    这个错误经常发生,代码如下: private  static  byte[] GetBytes (Image image) { try { if (image == null) return null ...

  2. 在asp.net mvc模式中使用PartialView返回部分HTML

    PartialView(返回HTML(局部)) 在asp.net mvc中返回View时使用的是ViewResult,它继承自ViewResultBase 同时它还有个兄弟PartialViewRes ...

  3. XSS攻击及防御

    XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性.其原理是攻击者向有XSS漏洞的网站中输入 ...

  4. 二、CoreAnimation之寄宿图详解

    在之前的图层树中我们知道,可以使用CALayer对象创建一些有背景颜色的图层,其实使用CALayer,不仅可以利用其展示背景颜色,还可以展示图片.而这些展示内容,其实就是CALayer的寄宿图.这一节 ...

  5. java ArrayList 实现

    关于ArrayList的实现和原理,原文出处:http://www.cnblogs.com/ITtangtang/p/3948555.html 我觉得他写的非常好,真的很好. 做一个记录和总结吧 pu ...

  6. python之sys模块详解

    python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...

  7. Spring中bean的作用域scope详解

    参考文献:http://blog.csdn.net/jacklearntech/article/details/40157861 http://www.cnblogs.com/qq78292959/p ...

  8. UWP 禁止Pivot swip 手势

    以前想要禁止内置的手势动作,看了一下网上是设置 IsLocked="True". 但是拿到UWP上来,靠,设置了之后header只显示当前的那个header.这样的设计真是丑爆了. ...

  9. Html 移动web开发细节处理

    1.-webkit-tap-highlight-color:rgba(255,255,255,0)可以同时屏蔽ios和android下点击元素时出现的阴影.备注:transparent的属性值在and ...

  10. Android中的ANR

    有过Android开发经历的人都不会对ANR陌生,它和崩溃一样是程序设计的问题.本文将以较为深入的视角来介绍什么是ANR,出现场景,如何避免以及如何定位分析ANR,希望可以帮助大家在编写程序时有所帮助 ...