关闭

httpclient +protobuf 实现数据传输

5315人阅读 评论(1) 收藏 举报
分类:

最近项目要接入某联盟广告,采用protobuf作为传输协议,以前没弄过,这次刚好使用到了,整理下

一、环境准备:(mac下)

1.1 下载protobuf2.5安装包

[html] view plain copy
  1. http://pan.baidu.com/s/1o6v4Sae  
1.2 解压安装包

[html] view plain copy
  1. tar -zxf  protobuf-2.5.0.tar.gz  
1.3 进入软件目录

[html] view plain copy
  1. cd protobuf-2.5.0  
1.4 设置编译目录

[html] view plain copy
  1. ./configure --prefix=/User/jack/software/tools/protobuf  
  2.  /User/jack/software/tools/protobuf  为自己设定的编译安装目录  
1.5 安装

[html] view plain copy
  1. make  
  2. make install  
1.6 配置环境变量

[html] view plain copy
  1. sudo vi .bash_profile  
  2. export PROTOBUF=/Users/jack/software/tools/protobuf  
  3. export PATH=$PROTOBUF/bin:$PATH  
1.7 验证

[html] view plain copy
  1. jack-3:bin jack$ protoc --version  
  2. libprotoc 2.5.0  

二、代码编写

2.1 查看.proto文件,只贴出了部分文件内容

[html] view plain copy
  1. package mobads.apiv5;  
  2. // 本文件描述API接口版本:5.0.0  
  3.   
  4. // 版本号信息  
  5. message Version {  
  6.     optional uint32 major = 1[default = 0]; // 必填!  
  7.     optional uint32 minor = 2[default = 0]; // 选填!  
  8.     optional uint32 micro = 3[default = 0]; // 选填!  
  9. };  

2.2 下载 protobuf-java-2.5.0.jar

[html] view plain copy
  1. http://download.csdn.net/download/zinc2008/8128155  

2.3 生成.java文件

[html] view plain copy
  1. protoc --java_out=./ baidu_mobads_api_5.0.proto  

同样只贴出部分java源文件 ( 注意java文件不要修改哦)

[html] view plain copy
  1. // Generated by the protocol buffer compiler.  DO NOT EDIT!  
  2. // source: baidu_mobads_api_5.0.proto  
  3.   
  4. package mobads.apiv5;  
  5.   
  6. public final class BaiduMobadsApi50 {  
  7.   private BaiduMobadsApi50() {}  
  8. }  


2.4 代码编写,只贴出关键部分

[html] view plain copy
  1. MobadsRequest adrequest = MobadsRequest.newBuilder().setRequestId(requestId).setAdslot(adslot).build();  
  2.   
  3. byte[] content = adrequest.toByteArray();  
  4.           
  5. HttpClient client = new HttpClient();   
  6. PostMethod postMethod = new PostMethod(URL);    
  7. postMethod.addRequestHeader("Content-Type", "application/octet-stream;charset=utf-8");  
  8. postMethod.setRequestEntity(new ByteArrayRequestEntity(content ));    
  9. client.executeMethod(postMethod);    
  10.             

注意content-type 设置为application/octet-stream。


到此,就完成了通过httpclient的post请求传输protobuf二进制流。

使用protobuf,所有的参数和返回都是对象的形式,这点还是用着比较爽的。


String byte 切换方法

服务端返回字符串


方式一:

[java] view plain copy
  1. Arrays.toString(personInfo.toByteArray())  

方式二:

[java] view plain copy
  1. toByteString().toStringUtf8()  


客户端解析字符串

方式一:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private static byte[] fromString(String string) {  
  2.     String[] strings = string.replace("[""").replace("]""").split(", ");  
  3.     byte[] result = new byte[strings.length];  
  4.     for (int i = 0; i < result.length; i++) {  
  5.         result[i] = Byte.parseByte(strings[i]);  
  6.     }  
  7.     return result;  
  8. }  
  9.   
  10. XXX.parseFrom(fromString(byteString))  

方式二:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. XXX.parseFrom(ByteString.copyFromUtf8(utf8ByteString))  


protobuf已经出来好多年了,原谅我最近才了解到google这个高性能的用于传输的格式。

 

从各方面来看,它无论从序列化的性能还是从序列化的压缩比都是优于当前各种传输格式的。如json、xml、hessian,java原生的Serializable。具体对比结果参见:http://agapple.iteye.com/blog/859052

 

网上也看了些资料,并有所了解,看了下,这玩意儿性能上来说真的没什么可说,但初始化和使用的时候感觉不是特别方便。而且网上的例子多数都是序列化过程,没有很多关于演示网络传输的demo,于是自己简单写了一个,将完整的例子摆在这里。

 

先定义一个Person.proto

 

Java代码  收藏代码
  1. option java_package = "com.example.protobuf";  
  2. option java_outer_classname = "PersonProbuf";  
  3.   
  4. message Person {  
  5.   required string name = 1;  
  6.   required int32 id = 2;  
  7.   optional string email = 3;  
  8.   repeated PhoneNumber phone = 4;  
  9.   
  10.   enum PhoneType {  
  11.     MOBILE = 0;  
  12.     HOME = 1;  
  13.     WORK = 2;  
  14.   }  
  15.   
  16.   message PhoneNumber {  
  17.     required string number = 1;  
  18.     optional PhoneType type = 2 [default = HOME];  
  19.   }  
  20. }  

 使用protoc生成对应的PersonProtobuf类

 

 

Java代码  收藏代码
  1. protoc.exe Person.proto --java_out=.  

 

 

请求客户端代码如下:

 

Java代码  收藏代码
  1. PersonProbuf.Person.Builder personRequest = PersonProbuf.Person.newBuilder();  
  2. personRequest.setId(1);  
  3. personRequest.setName("jesse");  
  4. personRequest.setEmail("xx@xx.com");  
  5.         personRequest.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("1234567890").setType(PersonProbuf.Person.PhoneType.HOME));  
  6.   
  7. //使用java原生URL连接代码生成请求并获得返回值打印          
  8. URL url = new URL("http://localhost:90/protobuf.jsp");  
  9. URLConnection connection = url.openConnection();  
  10. connection.setDoOutput(true);  
  11. personRequest.build().writeTo(connection.getOutputStream());  
  12.           
  13. PersonProbuf.Person personResponse = PersonProbuf.Person.parseFrom(connection.getInputStream());  
  14. System.out.println(personResponse.getId());  
  15. System.out.println(personResponse.getName());  
  16. System.out.println(personResponse.getEmail());  
  17. System.out.println(personResponse.getPhone(0));  
  18. System.out.println(personResponse.getPhone(1));  

  

服务端protobuf.jsp代码如下:

 

Java代码  收藏代码
  1. <%@ page pageEncoding="UTF-8"%>  
  2. <%@page import="com.example.protobuf.PersonProbuf"%>  
  3. <%  
  4. PersonProbuf.Person person = PersonProbuf.Person.parseFrom(request.getInputStream());  
  5. System.out.println(person.getId());  
  6. System.out.println(person.getName());  
  7. System.out.println(person.getEmail());  
  8. System.out.println(person.getPhone(0));  
  9. PersonProbuf.Person.Builder personBuilder = person.newBuilder(person);  
  10. personBuilder.setId(2);  
  11. personBuilder.setName("tiger");  
  12. personBuilder.setEmail("yy@yy.com");  
  13. personBuilder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("0987654321").setType(PersonProbuf.Person.PhoneType.HOME));  
  14. personBuilder.build().writeTo(response.getOutputStream());  
  15. %>  

 

执行客户端代码后,服务端/客户端输出:

Java代码  收藏代码
  1. ------服务端输出------  
  2. 1  
  3. jesse  
  4. xx@xx.com  
  5. number: "1234567890"  
  6. type: HOME  
  7.   
  8. ------客户端输出------  
  9. 2  
  10. tiger  
  11. yy@yy.com  
  12. number: "1234567890"  
  13. type: HOME  
  14.   
  15. number: "0987654321"  
  16. type: MOBILE  

 

 

所以protobuf只是一种序列化的格式,并不是传输协议,需要传输的,只要使用输入输出流,就可以做任何保存,传输的操作。

 

另外百度写了个jprotobuf开源,使用起来挺方便,只要使用注解放在javabean上就可以了

github:https://github.com/jhunters/jprotobuf

不过这个开源工具对集合没有适合的注解,而且也没有说明和其他语言传输的时候,如何保证一致性,所以需要使用的人考虑清楚,需要慎用。


3
0
查看评论

http请求使用protobuf通信

服务端返回字符串 方式一: Arrays.toString(personInfo.toByteArray()) 方式二: toByteString().toStringUtf8() 客户端解析字符串 方式一: private static byte[] fromS...
  • linminqin
  • linminqin
  • 2014-12-01 16:24
  • 5759

使用protobuf作为http通讯格式

protobuf谷歌的开源序列化项目,类似的还有于json,xml等组织格式;据说protobuf的序列化占用的数据量最下,传输效率最高,并且作为服务器开发者,只需要掌握.proto文件的书写方式,就可以生成不同语言的序列化对象。这次讲解一下如何在服务器和安卓客户端之间利用protobuf传输数据。...
  • jike0901xuye
  • jike0901xuye
  • 2017-05-04 21:33
  • 948

protobuf实现js与java间的http通信

protobuf js java
  • zhuyijian135757
  • zhuyijian135757
  • 2016-08-23 22:28
  • 5974

google protobuf学习笔记二:使用和原理

一.什么是protobuf protobuf全称Google Protocol Buffers,是google开发的的一套用于数据存储,网络通信时用于协议编解码的工具库。它和XML或者JSON差不多,也就是把某种数据结构的信息,以某种格式(XML,JSON)保存起来,protobuf与XML和JSO...
  • majianfei1023
  • majianfei1023
  • 2015-04-19 19:57
  • 21774

protobuf协议语言指南

Protobuf语言指南 l  定义一个消息(message)类型 l  标量值类型 l  Optional 的字段及默认值 l  枚举 l  使用其他消息类型 l  嵌套类型 l  更新一个消息类型 l ...
  • zhaozheng7758
  • zhaozheng7758
  • 2011-09-05 11:16
  • 32577

C++ protobuf使用方法

转自:http://www.cppblog.com/jack-wang/archive/2013/11/22/204378.aspx 下载protobuf-2.5.0(解压到D:\下) 编译,在目录D:\protobuf-2.5.0\vsprojects\Debug之下,生成若干.lib,.ex...
  • u014538198
  • u014538198
  • 2017-05-24 11:25
  • 716

C#版protobuf如何实现http方式二进制传输

  • 2013-05-18 11:02
  • 978KB
  • 下载

Protobuf的那些事

当大多数公司还在纠结于如何更好提高MobileAPI的性能时,有的公司已经开始抛弃http + json,开始走向tcp + protobuf的路线了。 那么什么是protobuf呢:protobuf是一种基于二进制的协议,它能够非常快速高效的序列化数据,考虑之前的xml,但是它的体积要比xml小的...
  • u013022222
  • u013022222
  • 2016-01-15 14:09
  • 11825

对protobuf的深入解释

对protobuf的深入解释   对protobuf俺的认识,总结为以下几点: 1.  pb是一种编码方式。 之所以这么说是因为有的人认为它是协议,那就侠义化了,pb本质上就和json、xml类似,是一种编码方式,用pb编码出来的流可以套在任何现有协议里面,作为...
  • oldworm
  • oldworm
  • 2012-07-06 14:38
  • 10789

httpclient +protobuf 实现数据传输

最近项目要接入某联盟广告,采用protobuf左右传输协议,以前没弄过,这次刚好使用到了,整理下 一、环境准备:(mac下) 1.1 下载protobuf2.5安装包 http://pan.baidu.com/s/1o6v4Sae1.2 解压安装包 tar -zxf protobuf...
  • hsbirenjie
  • hsbirenjie
  • 2015-08-04 19:43
  • 2397
    个人资料
    • 访问:9379504次
    • 积分:78620
    • 等级:
    • 排名:第21名
    • 原创:264篇
    • 转载:2876篇
    • 译文:3篇
    • 评论:800条
    文章分类
    最新评论