Protocol Buffer

来源:互联网 发布:合同管理风险控制矩阵 编辑:程序博客网 时间:2024/05/21 05:21
 

Java中使用Protocol Buffer

标签: protocol buffer
 418人阅读 评论(0) 收藏 举报
 分类:

目录(?)[+]

一、Protocol Buffer简介

什么是 Google Protocol Buffer? 假如您在网上搜索,应该会得到类似这样的文字介绍:
Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。
如果你在开发中使用过常用的数据交换格式如xml、json,那么protocol buffer也不是什么神奇的东西了,它和xml、json类似,也可以作为开发中的一种数据交换格式,只不过相较xml和json,protocol buffer的优点更明显,它更小、更快、更简单。

二、Protocol Buffer的使用(Java)

下面用一个例子来说明如何在Java中使用Protocol Buffer。

首先我们需要去Google的网站上下载Protocol Buffer的编译器:https://developers.google.com/protocol-buffers/docs/downloads,这里注意需要科学上网。

在Java中使用ProtocolBuffer的步骤大致分为下面这几点:

(1)编写.proto文件,定义消息类型

(2)使用ProtocolBuffer的编译器,将.proto文件编译成对应的java文件

(3)在Java代码中使用上一步编译好的java文件

如何编写.proto文件呢,看下面一个例子:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.demo.msg;  
  2.   
  3. option java_outer_classname = "PersonBean";  
  4.   
  5. message Person {  
  6.     required string name = 1;  
  7.     required int32 age = 2;  
  8.     optional string gender = 3;  
  9. }  
上面的代码可以保存到一个Person.proto文件中,其中package指定了包名,和java中的包名类似,option java_outer_classname = "PersonBean";这句指定了编译器在编译.proto文件时,输出的java类的类名,接着使用message定义了一个名为Person的消息,里面包含3个成员变量,其中用required修饰的变量代表必须的,optional修饰的变量代表是可选的,这里定义消息的形式跟java中定义类非常相似。

下面需要用ProtocolBuffer的编译器来编译上面的消息,我们从google的网站上下载下来的是一个protoc.exe文件,将该文件跟上面定义的消息文件Person.proto放在同一个目录下,然后在命令行中进入该目录,执行下面的命令:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. protoc.exe --java_out=./ Person.proto  
就在当前目录下生成了对应的java文件PersonProto.java

下面可以在Java项目中使用上面编译好的PersonProto.java文件了,我们新建一个java项目,项目结构如下:


上面需要注意的是,我们在lib目录下引入了protobuf-java-2.5.0.jar包,这个包就是用来对ProtocolBuffer消息进行序列化和反序列化的.

下面定义一个Server类,用于处理客户端发送过来的消息,代码如下:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.demo.server;  
  2.   
  3. import com.demo.constant.Constants;  
  4. import com.demo.msg.PersonBean;  
  5. import com.google.protobuf.ByteString;  
  6.   
  7. import java.net.ServerSocket;  
  8. import java.net.Socket;  
  9.   
  10. /** 
  11.  * Created by yubo7 on 2016/8/16. 
  12.  */  
  13. public class Server {  
  14.   
  15.     public static void main(String[] args) throws Exception {  
  16.         ServerSocket ss = new ServerSocket(Constants.PORT);  
  17.         System.out.println("server started...");  
  18.         Socket socket = ss.accept();  
  19.         System.out.println("a client connected!");  
  20.         //从输入流中解析出Person对象  
  21.         PersonBean.Person person = PersonBean.Person.parseFrom(ByteString.readFrom(socket.getInputStream()));  
  22.         if(person != null) {  
  23.             System.out.println("server received data:\n" + person.toString());  
  24.         }  
  25.     }  
  26.   
  27. }  
下面定义一个Client类,用于生成一个Person类并发送给Server,代码如下:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.demo.client;  
  2.   
  3. import com.demo.constant.Constants;  
  4. import com.demo.msg.PersonBean;  
  5.   
  6. import java.io.OutputStream;  
  7. import java.net.Socket;  
  8.   
  9. /** 
  10.  * Created by yubo7 on 2016/8/16. 
  11.  */  
  12. public class Client {  
  13.   
  14.     public static void main(String[] args) throws Exception {  
  15.         Socket socket = new Socket("localhost", Constants.PORT);  
  16.         //构造一个Person对象  
  17.         PersonBean.Person person = PersonBean.Person.newBuilder().setName("zhangsan")  
  18.                 .setAge(20).setGender("male").build();  
  19.         OutputStream os = socket.getOutputStream();  
  20.         //将Person对象写到输出流中  
  21.         os.write(person.toByteArray());  
  22.         os.flush();  
  23.         //这里注意一定要关闭流,否则服务端会报错  
  24.         os.close();  
  25.         System.out.println("client send person");  
  26.     }  
  27.   
  28. }  
上面的PORT为常量,定义在Constants类中,代码如下:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.demo.constant;  
  2.   
  3. /** 
  4.  * Created by yubo7 on 2016/8/16. 
  5.  */  
  6. public class Constants {  
  7.   
  8.     public static final int PORT = 9988;  
  9.   
  10. }  
到这里就可以测试程序了,我们先启动Server,在控制台打印的内容如下图:




然后再启动Client,在控制台打印的内容如下图:

然后再切换回Server的控制台,可以看到控制台中的打印如下图:

可以看到,控制台中打印了客户端发送过去的Person消息,这样,一个使用ProtocolBuffer来进行数据发送和接收的java程序就完成了。

本文源代码已托管到GitHub:https://github.com/yubo725/ProtocolBufferDemo

参考文章:http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/

0 0