[关闭]
@linux1s1s 2016-04-28T18:17:18.000000Z 字数 2995 阅读 2625

Protocol Buffers 浅析

Java 2016-04


简介

Protocol Buffers(简称protobuf)是谷歌的一项技术,用于将结构化的数据序列化、反序列化,经常用于网络传输。
这货实际上类似于XML生成和解析,但protobuf的效率高于XML,不过protobuf生成的是字节码,可读性比XML差。类似的还有json、Java的Serializable等。
详细了解可以参考Protocol Buffers,接下类将介绍一些基本的使用步骤。

使用

首先通读Protocol Buffers,了解.proto文件的基本格式和写法,下载官方给我们准备的工具,通过该工具可以将.proto文件直接生成需要的代码源文件(比如Java/C/C++/Python等等),接下来直接将该源文件放到工程目录中,编写相应的序列化和反序列化等,这样就完成了整个流程,下面给出简单的实现步骤。

.proto文件

time.proto

  1. option java_package = "com.test.app.pb.common";
  2. option java_outer_classname = "TimeProto";
  3. message Time {
  4. optional int32 id = 1;
  5. optional int32 startTime = 2;
  6. optional int32 endTime = 3;
  7. optional int64 systemTime = 4;
  8. optional string countDownTip = 5;
  9. optional int32 sEffectiveTime = 6;
  10. optional int32 eEffectiveTime = 7;
  11. optional string startTip = 8;
  12. optional string endTip = 9;
  13. }

上面的1、2、3、4是unique numbered tag,是一个唯一标识。这也是整个编码中的亮点,想一探究竟的可以继续往下看。

通过工具生成代码

protoc工具使用的一般格式是:

  1. protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/xxx.proto
  2. protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto

其中SRC_DIRproto文件所在的目录,DST_DIR是编译proto文件后生成的结构体处理文件的目录

之后会生成对结构体time.proto中描述的各字段做序列化反序列化的类。
工具命令如下:
此处输入图片的描述
生成的java代码
此处输入图片的描述

写测试代码

将上面生成的代码加入到工程中去,再将Jar包导入工程中,或者添加如下Maver依赖

  1. <dependency>
  2. <groupId>com.google.protobuf</groupId>
  3. <artifactId>protobuf-java</artifactId>
  4. <version>2.6.1</version>
  5. </dependency>

接下来写测试代码

序列化代码(发送方)

  1. TimeProto.Time.Builder timeBuilder = TimeProto.Time.newBuilder();
  2. timeBuilder.setEEffectiveTime(20160428)
  3. .setEndTime(20160429)
  4. .setEndTip("End")
  5. .setSEffectiveTime(20160428)
  6. .setStartTime(20160426)
  7. .setStartTip("Start")
  8. .setSystemTime(20160428);
  9. TimeProto.Time time = timeBuilder.build();
  10. ByteArrayOutputStream output = new ByteArrayOutputStream();
  11. try {
  12. time.writeTo(output);
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. }

反序列化(接收方)

  1. try {
  2. HttpClient httpClient = new DefaultHttpClient();
  3. url = NetworkUtils.getCompleteUrl(url, getParams);
  4. HttpGet request = new HttpGet(url);
  5. HttpResponse response = httpClient.execute(request);
  6. ByteArrayBuffer buffer = new ByteArrayBuffer(32 * 1024);
  7. InputStream in = null;
  8. try {
  9. HttpEntity entity = response.getEntity();
  10. if (entity == null) {
  11. } else {
  12. in = response.getEntity().getContent();
  13. }
  14. int temp;
  15. byte[] bytes = new byte[8096];
  16. while ((temp = in.read(bytes)) != -1) {
  17. buffer.append(bytes, 0, temp);
  18. }
  19. } catch (SocketTimeoutException e) {
  20. throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);
  21. } catch (IOException e) {
  22. throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);
  23. } finally {
  24. if (in != null) {
  25. try {
  26. in.close();
  27. } catch (IOException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }
  32. byte[] result = buffer.toByteArray();
  33. try {
  34. TimeProto.Time timeResp = TimeProto.Time.parseFrom(result);
  35. } catch (InvalidProtocolBufferException e) {
  36. e.printStackTrace();
  37. }
  38. } catch (SocketTimeoutException e) {
  39. throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);
  40. } catch (IllegalStateException e) {
  41. throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);
  42. } catch (IOException e) {
  43. throw new HttpException(HttpException.MSG_NETWORK_ERROR, e);
  44. }

关键的逻辑在L33到L35行,拿到字符数组以后直接parse出来。

参考文档:
Protocol Buffers 官方文档
Java使用Protocol Buffers入门四步骤 如何使用
google protobuf源码分析1源码分析
Protocol Buffer技术详解(Java实例) 如何使用
玩转Protocol Buffers 如何使用
Google Protocol Buffer 的使用和原理 原理和使用
Why Protocol Buffer So Fast? ----protobuf编码详解 原理和使用
Protocol Buffers编码详解,例子,图解 原理和使用

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注