无情 @ Mon Jan 11 15:27:44 CST 2016 阅读(1506)
protobuf



简介


protocol buffers是google提供的一种将结构化数据进行序列化和反序列化的方法,其优点是语言中立,平台中立,可扩展性好,目前在google内部大量用于数据存储,通讯协议等方面。PB在功能上类似XML,但是序列化后的数据更小,解析更快,使用上更简单。用户只要按照proto语法在.proto文件中定义好数据的结构,就可以使用PB提供的工具(protoc)自动生成处理数据的代码,使用这些代码就能在程序中方便的通过各种数据流读写数据。PB目前支持Java, C++和Python3种语言。另外,PB还提供了很好的向后兼容,即旧版本的程序可以正常处理新版本的数据,新版本的程序也能正常处理旧版本的数据。


一:安装


下载protobuf2.5 


google官方下载地址  https://github.com/google/protobuf(目前已经到3.0)


本人使用的是2.5下载地址是: https://github.com/google/protobuf/archive/v2.5.0.zip

解压:

tar -zxf  protobuf-2.5.0.tar.gz


cd protobuf-2.5.0

设置编译目录:


./configure --prefix=/usr/local/protobuf

 /usr/local/protobuf  为自己设定的编译安装目录

安装:

make

make install

配置环境变量:

 sudo  vim /etc/profile 

添加配置文件:

export PROTOBUF=/usr/local/protobuf

export PATH=$PROTOBUF/bin:$PATH


然后保存执行:

source /etc/profile 


测试:

protoc --version




二:实例(本人结合java)



1:eclipse安装protobuf插件

 插件地址: http://protobuf-dt.googlecode.com/git/update-site (由于google被屏蔽各位开发者这里需要墙)如图:

 

 

 

2: 配置protobuf插件  本人是maven工程


3:创建一个工程

   a:创建mobile.proto

   

 option java_package = "com.demo.vo";
   option java_outer_classname = "Mobile";
   message MobilePhone {
   required string brand = 1;
   required Hardware hardware = 2;
   repeated string software = 3;
   }
   message Hardware {
   required int32 rom = 1;
   required int32 ram = 2;
   required int32 size = 3;
   }


  b:客户端代码

package com.demo.protobuf;
  import java.net.Socket;
  import com.demo.vo.Mobile;
  public class Client {
      /**
       * @param args
       */
      public static void main(String[] args) throws Exception {
          Socket socket = new Socket("127.0.0.1", 3030);
          Mobile.MobilePhone.Builder builder = Mobile.MobilePhone.newBuilder();
          Mobile.Hardware.Builder hardware = Mobile.Hardware.newBuilder();
          hardware.setRam(2).setRom(16).setSize(5);
          builder.setHardware(hardware).setBrand("Apple").addSoftware("camera").addSoftware("tecent").addSoftware("browser").addSoftware("player");
          byte[] messageBody = builder.build().toByteArray();
          int headerLen = 1;
          byte[] message = new byte[headerLen + messageBody.length];
          message[0] = (byte) messageBody.length;
          System.arraycopy(messageBody, 0, message, 1, messageBody.length);
          System.out.println("msg len:" + message.length);
          socket.getOutputStream().write(message);
      }
  }

  

  c:服务端代码

package com.demo.protobuf;
  import java.net.ServerSocket;
  import java.net.Socket;
  import com.demo.vo.Mobile;
  import com.demo.vo.Mobile.MobilePhone;
  public class Server {
      /**
       * @param args
       */
      public static void main(String[] args) throws Exception {
          // TODO Auto-generated method stub
          ServerSocket serverSock = new ServerSocket(3030);
          Socket sock = serverSock.accept();
          byte[] msg = new byte[256];
          sock.getInputStream().read(msg);
          int msgBodyLen = msg[0];
          System.out.println("msg body len:" + msgBodyLen);
          byte[] msgbody = new byte[msgBodyLen];
          System.arraycopy(msg, 1, msgbody, 0, msgBodyLen);
          MobilePhone phone = Mobile.MobilePhone.parseFrom(msgbody);
          System.out.println("Receive:");
          System.out.println(phone.toString());
      }
  }

  

  

  运行结果如图:




  

  三:proto相关语法及其说明

  

  1 proto文件是对数据的一个描述,包括字段名称,类型,字节中的位置。

   索引号要按顺序指定

  相关数据类型


 


 2.数据类型前面的修饰词:


  required : 必须赋值,不能为空,否则该条message会被认为是“uninitialized”。build一个“uninitialized”    message会抛出一个RuntimeException异常,解析一条“uninitialized” message会抛出一条IOException异常。除此之外,“required”字段跟“optional”字段并无差别。

 optional :字段可以赋值,也可以不赋值。假如没有赋值的话,会被赋上默认值。

 repeated : 该字段可以重复任意次数,包括0次。重复数据的顺序将会保存在protocol buffer中,将这个字段想象成一个可以自动设置size的数组就可以了。