`
jackyhongvip
  • 浏览: 159613 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

RPC_PROTOBUL范例

    博客分类:
  • RPC
 
阅读更多

1.下载与安装

  官方网站:http://code.google.com/p/protobuf/

  下载地址:http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.bz2

  protocol buffers并没有实现RPC通信,可以使用第三方的RPC实现protobuf-socket-rpc,下载地址是:http://protobuf-socket-rpc.googlecode.com/files/protobuf-socket-rpc-2.0.jar

  1. cd /usr/local/src
  2. wget http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.bz2
  3. tar jxvf protobuf-2.4.1.tar.bz2
  4. cd protobuf-2.4.1
  5. ./configure
  6. make
  7. make check
  8. make install

 

  下面将编译生成jar包,以便在java中使用Protocol Buffers,需确保已安装了maven。

  1. cd java
  2. mvn test
  3. mvn install
  4. mvn package

  安装、编译后在target/目录下会生成protobuf-java-2.4.1.jar。

2.消息结构与服务接口

  首先需要编写一个.proto文件,结构化数据被称为Message。

  1. package protobuf;
  2.  
  3. option java_package = "protobuf";
  4. option java_outer_classname = "PersonProtos";
  5. option java_generic_services = true;
  6.  
  7. message Person {
  8.     required string name = 1;
  9.     required int32 id = 2;
  10.     optional string email = 3;
  11.  
  12.     enum PhoneType {
  13.         MOBILE = 0;
  14.         HOME = 1;
  15.         WORK = 2;
  16.     }
  17.  
  18.     message PhoneNumber {
  19.         required string number = 1;
  20.         optional PhoneType type = 2 [default = HOME];
  21.     }
  22.  
  23.     repeated PhoneNumber phone = 4;
  24.  
  25.     service PhoneService {
  26.         rpc GetPhone (Phone) returns (Phone);
  27.     }
  28. }

  消息的成员需要指定其规则:

    (1) required:这个域在消息中必须刚好有1个;

    (2) optional:这个域在消息中可以有0或1个;

    (3) repeated:这个域在消息中可以有从多个,包括0个。

  Protobuf的类型与Java类型的映射关系:

  1. double   ->  double
  2. float    ->  float
  3. int32    ->  int
  4. int64    ->  long
  5. uint32   ->  int[1]
  6. uint64   ->  long[1]
  7. sint32   ->  int
  8. sint64   ->  long
  9. fixed32  ->  int[1]
  10. fixed64  ->  long[1]
  11. sfixed32 ->  int
  12. sfixed64 ->  long
  13. bool     ->  boolean
  14. string   ->  String
  15. bytes    ->  ByteString

  编写完.proto文件后,就可以使用下面的命令将会在protobuf目录中生成源文件PersonProtos.java

  1. protoc –java_out=. person.proto

3.序列化

  先看下面一个例子:

  1. message Test1 {
  2.     required int32 a = 1;
  3. }

  创建一个Test1消息,并且把a设置为150,那么序列化后有如下3个字节:

  1. 08 96 01

3.1.varint编码

  varint编码的序列化使用一个或多个字节,数字越大使用的字节数越多。对于序列化后的字节,除了最后一个字节,都有一个most significant bit(msb):表示后边是否有更多的字节。整数序列化时按7位一组,每个字节的低7位保存一组,第一个字节存储最低位一组,即使用little endian。

  比如300序列化后的字节序列是:

  1. 10101100 00000010

  先去掉每个字节的msb:

  1. 0101100 0000010

  交换字节的顺序:

  1. 0000010 0101100 -> 100101100 -> 256 + 32 + 8 + 4 = 300

3.2.消息结构

  一个protocol buffer message是一个key/value对序列。每一key/value对的key实际是两个值:.proto文件中的field number以及wire type。可用的wire type如下所示:


Type Meaning Used For
0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit fixed64, sfixed64, double
2 Length-delimited string, bytes, embedded messages, packed repeated fields
3 Start group groups (deprecated)
4 End group groups (deprecated)
5 32-bit fixed32, sfixed32, float

  每一个key是一个varint,值是(field_number << 3) | wire_type,即低三位存储wire type。

3.3.有符号整数

  有符号整数使用ZigZag编码来将有符号整数映射到无符号整数。


Signed Original Encoded As
0 0
-1 1
1 2
-2 3
2147483647 4294967294
-2147483648 4294967294

3.4.非varint编码

  1. message Test2 {
  2.     required string b = 2;
  3. }

  将b的值设置为“testing”,编码结果为:

  1. 12 07 74 65 73 74 69 6e 67

  这里的key是0×12:field_number = 2, type = 2。字符串的长度是7。

3.5.嵌套消息

  1. message Tes3 {
  2.     required Test1 c = 3;
  3. }

  c的成员a的值设置为150,编码结果为:

  1. 1a 03 08 96 01

  后三个字节和Test1一样,之前的数字3表示长度。

3.5.Repeated域

  1. message Test4 {
  2.     repeated int32 d = 4;
  3. }

  {3, 270, 86942}编码结果为:

  1. 22        // tag (field number 4, wire type 2)
  2. 06        // payload size (6 bytes)
  3. 03        // first element (varint 3)
  4. 8E 02     // second element (varint 270)
  5. 9E A7 05  // third element (varint 86942)

4.rpc通信实现

  使用protocol buffers的第三方rpc实现protobuf-socket-rpc。

  假设protocol buffers生成的类是protobuf. MessageProtos,其中定义了一个消息类Message和一个服务类MessageService,MessageService中定义了一个接口getMessage(RpcController, Message request)。

  服务接口实现MessageServiceImpl.java:

  1. package protobuf;
  2.  
  3. import com.google.protobuf.RpcController;
  4. import com.google.protobuf.ServiceException;
  5. import protobuf.MessageProtos.Message;
  6. import protobuf.MessageProtos.MessageService.BlockingInterface;
  7.  
  8. public class MessageServiceImpl implements BlockingInterface {
  9.     @Override
  10.     public Message getMessage(RpcController controller, Message request)
  11.             throws ServiceException {
  12.         // process request       
  13.     ……
  14.         return request;
  15.     }
  16. }

  服务端实现Server.java:

  1. package protobuf;
  2.  
  3. import java.util.concurrent.Executors;
  4.  
  5. import com.googlecode.protobuf.socketrpc.RpcServer;
  6. import com.googlecode.protobuf.socketrpc.ServerRpcConnectionFactory;
  7. import com.googlecode.protobuf.socketrpc.SocketRpcConnectionFactories;
  8. import protobuf.MessageProtos.MessageService;
  9.  
  10. public class Server {
  11.     private int port;
  12.     private int threadPoolSize;
  13.  
  14.     public Server(int port, int threadPoolSize) {
  15.         this.port = port;
  16.         this.threadPoolSize = threadPoolSize;
  17.     }
  18.  
  19.     public void run() {
  20.         // Start server
  21.         ServerRpcConnectionFactory rpcConnectionFactory = SocketRpcConnectionFactories
  22.                 .createServerRpcConnectionFactory(port);
  23.         RpcServer server = new RpcServer(rpcConnectionFactory,
  24.                 Executors.newFixedThreadPool(threadPoolSize), true);
  25.         server.registerBlockingService(MessageService
  26.                 .newReflectiveBlockingService(new MessageServiceImpl()));
  27.         server.run();
  28.     }
  29.  
  30.     public static void main(String[] args) {
  31.         if (args.length != 2) {
  32.             System.out.println("Usage: Server port thread_pool_size");
  33.             return;
  34.         }
  35.  
  36.         int port = Integer.parseInt(args[0]);
  37.         int size = Integer.parseInt(args[1]);
  38.  
  39.         new Server(port, size).run();
  40.     }
  41. }

  客户端实现Client.java:

  1. package protobuf;
  2.  
  3. import protobuf.MessageProtos.Message;
  4. import protobuf.MessageProtos.MessageService;
  5. import protobuf.MessageProtos.MessageService.BlockingInterface;
  6.  
  7. import com.google.protobuf.BlockingRpcChannel;
  8. import com.google.protobuf.ByteString;
  9. import com.google.protobuf.RpcController;
  10. import com.google.protobuf.ServiceException;
  11. import com.googlecode.protobuf.socketrpc.RpcChannels;
  12. import com.googlecode.protobuf.socketrpc.RpcConnectionFactory;
  13. import com.googlecode.protobuf.socketrpc.SocketRpcConnectionFactories;
  14. import com.googlecode.protobuf.socketrpc.SocketRpcController;
  15.  
  16. public class Client {
  17.     private int port;
  18.     private String host;
  19.     private int size;
  20.     private int count;
  21.  
  22.     public Client(int port, String host, int size, int count) {
  23.         super();
  24.         this.port = port;
  25.         this.host = host;
  26.         this.size = size;
  27.         this.count = count;
  28.     }
  29.  
  30.     public long run() {
  31.         // Create channel
  32.         RpcConnectionFactory connectionFactory = SocketRpcConnectionFactories
  33.                 .createRpcConnectionFactory(host, port);
  34.         BlockingRpcChannel channel = RpcChannels
  35.                 .newBlockingRpcChannel(connectionFactory);
  36.  
  37.         // Call service
  38.         BlockingInterface service = MessageService.newBlockingStub(channel);
  39.         RpcController controller = new SocketRpcController();
  40.         Message.Builder message = Message.newBuilder();
  41.         // initiate the message
  42.         …
  43.  
  44.         long start = 0;
  45.         long end = 0;
  46.         try {
  47.             start = System.currentTimeMillis();
  48.             for (int i = 0; i < count; i++) {
  49.                 service.getMessage(controller, message.build());
  50.             }
  51.             end = System.currentTimeMillis();
  52.             System.out.println(end - start);
  53.         } catch (ServiceException e) {
  54.             e.printStackTrace();
  55.         }
  56.  
  57.         // Check success
  58.         if (controller.failed()) {
  59.             System.err.println(String.format("Rpc failed %s : %s",
  60.                     ((SocketRpcController) controller).errorReason(),
  61.                     controller.errorText()));
  62.         }
  63.  
  64.         return end - start;
  65.     }
  66.  
  67.     public static void main(String[] args) {
  68.         if (args.length != 4) {
  69.             System.out.println("Usage: Client host port dataSize count");
  70.             return;
  71.         }
  72.         String host = args[0];
  73.         int port = Integer.parseInt(args[1]);
  74.         int size = Integer.parseInt(args[2]);
  75.         int count = Integer.parseInt(args[3]);
  76.  
  77.         new Client(port, host, size, count).run();
  78.     }
  79. }

5.参考资料

  (1) Protocol Buffers Documentation: http://code.google.com/apis/protocolbuffers/docs/overview.html

分享到:
评论

相关推荐

    ONCRPC.rar_ONCRPC_code rpc_onc_onc rpc

    这个"ONCRPC.rar_ONCRPC_code rpc_onc_onc rpc"文件包含的是关于ONC RPC协议的实现代码,主要针对的是JAVA平台,旨在实现不同编程语言之间的RPC调用。 在RPC(Remote Procedure Call)机制中,客户端可以透明地调用...

    ONCRPC.zip_ONCRPC_onc_onc rpc_onc rpc_visual c

    这个“ONCRPC.zip_ONCRPC_onc_onc_rpc_onc_rpc_visual_c”压缩包包含了与ONC RPC相关的库和源码,特别适合于Windows系统开发人员,特别是那些使用Visual C++作为编程环境的开发者。 ONC RPC的核心是RPC(Remote ...

    RPC.tar.gz_linux rpc_rpc_rpc linux_rpc linux_C

    本资料包“RPC.tar.gz_linux rpc_rpc_rpc linux_rpc linux_C”提供了C语言实现的RPC功能,旨在帮助开发者理解和应用Linux环境下的RPC技术。 首先,让我们深入理解RPC的工作原理。RPC的核心思想是客户端发起一个请求...

    phprpc_3.0.2_delphi_Edit_XE2

    在这个特定的版本"phprpc_3.0.2_delphi_Edit_XE2"中,重点是针对Embarcadero Delphi开发环境的一个定制编辑版,特别适配于XE2版本。这表明该版本是为使用Delphi XE2的开发者设计的,旨在方便他们在PHP和Delphi之间...

    RPC-code_rpc_

    在本项目"RPC-code_rpc_"中,我们关注的是RPC的实现,特别是通过Thrift和RMI两种技术进行服务器间的交互。 **Thrift** 是Facebook开源的一种高性能、跨语言的服务交互框架。它的主要功能是生成跨语言的客户端和...

    rpc.rar_The Just_rpc_rpc/rpc.h

    4. **RPC函数原型**:如`rpc_create()`, `rpc_destroy()`, `rpc_call()`, `rpc_reply()`等,这些函数实现了RPC的核心功能,包括创建RPC客户端和服务端、发起调用、处理响应等。 5. **错误处理**:RPC调用可能因网络...

    odoo_rpc_client.py

    python语言json-rpc方式和odoo通讯,抛砖引玉,仅获取版本功能。用得是odoo专门给python提供的接口.

    RPC.rar_RPC image_rational _rpc_satellite

    在本例中,“RPC.rar_RPC image_rational_rpc_satellite”指的是一个与遥感卫星图像处理相关的RPC技术应用。RPC在卫星图像处理中的作用主要是将遥感数据转换为地理坐标,实现图像的空间定位。 RPC模型在卫星图像...

    phprpc_3.0.1_delphi

    Phprpc_3.0.1_Delphi 是一个基于RPC(Remote Procedure Call)协议的开源框架,专门设计用于实现不同编程语言之间的数据共享和交互。RPC允许程序在不同的网络节点上执行远程调用,就像调用本地函数一样简单,极大地...

    JsonRpc.rar_C++ jsonrpc_JSON_JsonRpc.rar_json-rpc _用jsonrpc封装

    JSON-RPC是一种轻量级的远程过程调用(RPC)协议,它使用JSON(JavaScript Object Notation)作为数据交换格式。在C++中实现JSON-RPC可以为软件开发带来诸多便利,例如跨语言通信、简化接口设计等。你提供的"JsonRpc...

    RPC.rar_C++ 远程调用_VC6.0 开发RPC_windows RPC_远程过程调用

    RPC,即Remote Procedure Call(远程过程调用),是计算机网络编程中的一个重要概念,它允许一个程序在不理解底层网络协议的情况下,调用另一个网络上不同机器上的程序。在这个"RPC.rar"压缩包中,主要围绕C++语言在...

    XML-RPC.rar_python xml rpc_python写xml_xml rpc_xml-rpc python

    在这个"XML-RPC.rar"压缩包中,包含了一系列Python实现的XML-RPC相关文件,包括server.py、readfile.py、client.py和D_H.py,这些都是实现XML-RPC服务端和客户端功能的关键代码。 首先,我们来看`server.py`。这个...

    PyPI 官网下载 | hived_rpc_scanner-0.0.3.tar.gz

    《PyPI官网下载:深入理解hived_rpc_scanner-0.0.3.tar.gz》 在Python编程领域,PyPI(Python Package Index)是全球最大的Python软件仓库,它提供了丰富的Python库供开发者下载和使用。当我们看到“hived_rpc_...

    PyPI 官网下载 | rpc_zigzag-0.12.1-py2.py3-none-any.whl

    在本例中,我们讨论的是在PyPI官网上发布的`rpc_zigzag`库的一个版本,具体为`0.12.1`。 `rpc_zigzag-0.12.1-py2.py3-none-any.whl`这个文件是Python的轮子(wheel)格式,它是预编译的Python包,旨在简化安装过程...

    oncrpc_vxi11_test.rar

    windows下vxi11实现示例代码,用于实现仪器的远程发现,远程控制。作为VXI协议族的一部分,VXI-11协议用于解决控制计算机与仪器间通过TCP/IP网络通信的问题。它用于实现仪器间数据传输的核心通道、异常通道以及中断...

    oncrpc.rar_RPC. VC++_oncrpc windows_windows RPC_ycnian的博客

    RPC(Remote Procedure Call)是一种分布式计算技术,允许一个程序在一台计算机上执行远程操作,就像它在本地执行一样。在Windows环境下,RPC是系统服务的重要组成部分,广泛用于进程间通信和系统组件之间的交互。本...

    rpc_pipe.rar_V2

    "rpc_pipe"指的是在RPC框架下使用管道(pipe)作为通信机制的一个组件。 标题中的"rpc_pipe.rar_V2"很可能是指RPC管道实现的一个特定版本,这里的"V2"可能代表版本2。这个压缩包文件包含的是"rpc_pipe.c"源代码文件...

    phprpc_client

    phprpc的客户端jar包,没有其他要说的了

    phprpc_client.jar

    JAVA WEB开发中一个很强大的JAR包!

    phprpc_3.0.2_java,webservice

    总结来说,Phprpc_3.0.2_java是一个用于构建跨语言RPC通信的工具,特别适用于Java环境下的Web服务开发。它提供了一套简便的API,使得开发者可以轻松地实现服务的发布和调用,同时具备良好的性能和广泛的兼容性。

Global site tag (gtag.js) - Google Analytics