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
- cd /usr/local/src
- wget http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.bz2
- tar jxvf protobuf-2.4.1.tar.bz2
- cd protobuf-2.4.1
- ./configure
- make
- make check
- make install
下面将编译生成jar包,以便在java中使用Protocol Buffers,需确保已安装了maven。
- cd java
- mvn test
- mvn install
- mvn package
安装、编译后在target/目录下会生成protobuf-java-2.4.1.jar。
2.消息结构与服务接口
首先需要编写一个.proto文件,结构化数据被称为Message。
- package protobuf;
-
- option java_package = "protobuf";
- option java_outer_classname = "PersonProtos";
- option java_generic_services = true;
-
- message Person {
- required string name = 1;
- required int32 id = 2;
- optional string email = 3;
-
- enum PhoneType {
- MOBILE = 0;
- HOME = 1;
- WORK = 2;
- }
-
- message PhoneNumber {
- required string number = 1;
- optional PhoneType type = 2 [default = HOME];
- }
-
- repeated PhoneNumber phone = 4;
-
- service PhoneService {
- rpc GetPhone (Phone) returns (Phone);
- }
- }
消息的成员需要指定其规则:
(1) required:这个域在消息中必须刚好有1个;
(2) optional:这个域在消息中可以有0或1个;
(3) repeated:这个域在消息中可以有从多个,包括0个。
Protobuf的类型与Java类型的映射关系:
- double -> double
- float -> float
- int32 -> int
- int64 -> long
- uint32 -> int[1]
- uint64 -> long[1]
- sint32 -> int
- sint64 -> long
- fixed32 -> int[1]
- fixed64 -> long[1]
- sfixed32 -> int
- sfixed64 -> long
- bool -> boolean
- string -> String
- bytes -> ByteString
编写完.proto文件后,就可以使用下面的命令将会在protobuf目录中生成源文件PersonProtos.java
- protoc –java_out=. person.proto
3.序列化
先看下面一个例子:
- message Test1 {
- required int32 a = 1;
- }
创建一个Test1消息,并且把a设置为150,那么序列化后有如下3个字节:
3.1.varint编码
varint编码的序列化使用一个或多个字节,数字越大使用的字节数越多。对于序列化后的字节,除了最后一个字节,都有一个most significant bit(msb):表示后边是否有更多的字节。整数序列化时按7位一组,每个字节的低7位保存一组,第一个字节存储最低位一组,即使用little endian。
比如300序列化后的字节序列是:
先去掉每个字节的msb:
交换字节的顺序:
- 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编码
- message Test2 {
- required string b = 2;
- }
将b的值设置为“testing”,编码结果为:
- 12 07 74 65 73 74 69 6e 67
这里的key是0×12:field_number = 2, type = 2。字符串的长度是7。
3.5.嵌套消息
- message Tes3 {
- required Test1 c = 3;
- }
c的成员a的值设置为150,编码结果为:
后三个字节和Test1一样,之前的数字3表示长度。
3.5.Repeated域
- message Test4 {
- repeated int32 d = 4;
- }
{3, 270, 86942}编码结果为:
- 22 // tag (field number 4, wire type 2)
- 06 // payload size (6 bytes)
- 03 // first element (varint 3)
- 8E 02 // second element (varint 270)
- 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:
-
package protobuf;
-
-
import com.google.protobuf.RpcController;
-
import com.google.protobuf.ServiceException;
-
import protobuf.MessageProtos.Message;
-
import protobuf.MessageProtos.MessageService.BlockingInterface;
-
-
public class MessageServiceImpl implements BlockingInterface {
-
@Override
-
public Message getMessage(RpcController controller, Message request)
-
throws ServiceException {
-
// process request
- ……
-
return request;
-
}
- }
服务端实现Server.java:
-
package protobuf;
-
-
import java.util.concurrent.Executors;
-
-
import com.googlecode.protobuf.socketrpc.RpcServer;
-
import com.googlecode.protobuf.socketrpc.ServerRpcConnectionFactory;
-
import com.googlecode.protobuf.socketrpc.SocketRpcConnectionFactories;
-
import protobuf.MessageProtos.MessageService;
-
-
public class Server {
-
private int port;
-
private int threadPoolSize;
-
-
public Server(int port, int threadPoolSize) {
-
this.port = port;
-
this.threadPoolSize = threadPoolSize;
-
}
-
-
public void run() {
-
// Start server
-
ServerRpcConnectionFactory rpcConnectionFactory = SocketRpcConnectionFactories
-
.createServerRpcConnectionFactory(port);
-
RpcServer server = new RpcServer(rpcConnectionFactory,
-
Executors.newFixedThreadPool(threadPoolSize), true);
-
server.registerBlockingService(MessageService
-
.newReflectiveBlockingService(new MessageServiceImpl()));
-
server.run();
-
}
-
-
public static void main(String[] args) {
-
if (args.length != 2) {
-
System.out.println("Usage: Server port thread_pool_size");
-
return;
-
}
-
-
int port = Integer.parseInt(args[0]);
-
int size = Integer.parseInt(args[1]);
-
-
new Server(port, size).run();
-
}
- }
客户端实现Client.java:
-
package protobuf;
-
-
import protobuf.MessageProtos.Message;
-
import protobuf.MessageProtos.MessageService;
-
import protobuf.MessageProtos.MessageService.BlockingInterface;
-
-
import com.google.protobuf.BlockingRpcChannel;
-
import com.google.protobuf.ByteString;
-
import com.google.protobuf.RpcController;
-
import com.google.protobuf.ServiceException;
-
import com.googlecode.protobuf.socketrpc.RpcChannels;
-
import com.googlecode.protobuf.socketrpc.RpcConnectionFactory;
-
import com.googlecode.protobuf.socketrpc.SocketRpcConnectionFactories;
-
import com.googlecode.protobuf.socketrpc.SocketRpcController;
-
-
public class Client {
-
private int port;
-
private String host;
-
private int size;
-
private int count;
-
-
public Client(int port, String host, int size, int count) {
-
super();
-
this.port = port;
-
this.host = host;
-
this.size = size;
-
this.count = count;
-
}
-
-
public long run() {
-
// Create channel
-
RpcConnectionFactory connectionFactory = SocketRpcConnectionFactories
-
.createRpcConnectionFactory(host, port);
-
BlockingRpcChannel channel = RpcChannels
-
.newBlockingRpcChannel(connectionFactory);
-
-
// Call service
-
BlockingInterface service = MessageService.newBlockingStub(channel);
-
RpcController controller = new SocketRpcController();
-
Message.Builder message = Message.newBuilder();
-
// initiate the message
- …
-
-
long start = 0;
-
long end = 0;
-
try {
-
start = System.currentTimeMillis();
-
for (int i = 0; i < count; i++) {
-
service.getMessage(controller, message.build());
-
}
-
end = System.currentTimeMillis();
-
System.out.println(end - start);
-
} catch (ServiceException e) {
-
e.printStackTrace();
-
}
-
-
// Check success
-
if (controller.failed()) {
-
System.err.println(String.format("Rpc failed %s : %s",
-
((SocketRpcController) controller).errorReason(),
-
controller.errorText()));
-
}
-
-
return end - start;
-
}
-
-
public static void main(String[] args) {
-
if (args.length != 4) {
-
System.out.println("Usage: Client host port dataSize count");
-
return;
-
}
-
String host = args[0];
-
int port = Integer.parseInt(args[1]);
-
int size = Integer.parseInt(args[2]);
-
int count = Integer.parseInt(args[3]);
-
-
new Client(port, host, size, count).run();
-
}
- }
5.参考资料
(1) Protocol Buffers Documentation: http://code.google.com/apis/protocolbuffers/docs/overview.html
分享到:
相关推荐
这个"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”压缩包包含了与ONC RPC相关的库和源码,特别适合于Windows系统开发人员,特别是那些使用Visual C++作为编程环境的开发者。 ONC RPC的核心是RPC(Remote ...
本资料包“RPC.tar.gz_linux rpc_rpc_rpc linux_rpc linux_C”提供了C语言实现的RPC功能,旨在帮助开发者理解和应用Linux环境下的RPC技术。 首先,让我们深入理解RPC的工作原理。RPC的核心思想是客户端发起一个请求...
在这个特定的版本"phprpc_3.0.2_delphi_Edit_XE2"中,重点是针对Embarcadero Delphi开发环境的一个定制编辑版,特别适配于XE2版本。这表明该版本是为使用Delphi XE2的开发者设计的,旨在方便他们在PHP和Delphi之间...
在本项目"RPC-code_rpc_"中,我们关注的是RPC的实现,特别是通过Thrift和RMI两种技术进行服务器间的交互。 **Thrift** 是Facebook开源的一种高性能、跨语言的服务交互框架。它的主要功能是生成跨语言的客户端和...
4. **RPC函数原型**:如`rpc_create()`, `rpc_destroy()`, `rpc_call()`, `rpc_reply()`等,这些函数实现了RPC的核心功能,包括创建RPC客户端和服务端、发起调用、处理响应等。 5. **错误处理**:RPC调用可能因网络...
python语言json-rpc方式和odoo通讯,抛砖引玉,仅获取版本功能。用得是odoo专门给python提供的接口.
在本例中,“RPC.rar_RPC image_rational_rpc_satellite”指的是一个与遥感卫星图像处理相关的RPC技术应用。RPC在卫星图像处理中的作用主要是将遥感数据转换为地理坐标,实现图像的空间定位。 RPC模型在卫星图像...
Phprpc_3.0.1_Delphi 是一个基于RPC(Remote Procedure Call)协议的开源框架,专门设计用于实现不同编程语言之间的数据共享和交互。RPC允许程序在不同的网络节点上执行远程调用,就像调用本地函数一样简单,极大地...
JSON-RPC是一种轻量级的远程过程调用(RPC)协议,它使用JSON(JavaScript Object Notation)作为数据交换格式。在C++中实现JSON-RPC可以为软件开发带来诸多便利,例如跨语言通信、简化接口设计等。你提供的"JsonRpc...
RPC,即Remote Procedure Call(远程过程调用),是计算机网络编程中的一个重要概念,它允许一个程序在不理解底层网络协议的情况下,调用另一个网络上不同机器上的程序。在这个"RPC.rar"压缩包中,主要围绕C++语言在...
在这个"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》 在Python编程领域,PyPI(Python Package Index)是全球最大的Python软件仓库,它提供了丰富的Python库供开发者下载和使用。当我们看到“hived_rpc_...
在本例中,我们讨论的是在PyPI官网上发布的`rpc_zigzag`库的一个版本,具体为`0.12.1`。 `rpc_zigzag-0.12.1-py2.py3-none-any.whl`这个文件是Python的轮子(wheel)格式,它是预编译的Python包,旨在简化安装过程...
windows下vxi11实现示例代码,用于实现仪器的远程发现,远程控制。作为VXI协议族的一部分,VXI-11协议用于解决控制计算机与仪器间通过TCP/IP网络通信的问题。它用于实现仪器间数据传输的核心通道、异常通道以及中断...
RPC(Remote Procedure Call)是一种分布式计算技术,允许一个程序在一台计算机上执行远程操作,就像它在本地执行一样。在Windows环境下,RPC是系统服务的重要组成部分,广泛用于进程间通信和系统组件之间的交互。本...
"rpc_pipe"指的是在RPC框架下使用管道(pipe)作为通信机制的一个组件。 标题中的"rpc_pipe.rar_V2"很可能是指RPC管道实现的一个特定版本,这里的"V2"可能代表版本2。这个压缩包文件包含的是"rpc_pipe.c"源代码文件...
phprpc的客户端jar包,没有其他要说的了
JAVA WEB开发中一个很强大的JAR包!
总结来说,Phprpc_3.0.2_java是一个用于构建跨语言RPC通信的工具,特别适用于Java环境下的Web服务开发。它提供了一套简便的API,使得开发者可以轻松地实现服务的发布和调用,同时具备良好的性能和广泛的兼容性。