java/php + protobuf 使用总结

在对接tron的项目时使用到了protobuf,在阅读官方文档的时候,发现有些地方文档写得并不清楚,于是记录如下的笔记作为补充备查。


关于Protobuf的使用[php]

  1. 查看protobuf官方文档,安装php扩展grpc.so和protobuf.so。前者在文档里有讲清楚,后者需要单独去搜索下载扩展安装包安装。
  2. 需要按文档编译安装 protoc和grpc_php_plugin,后续需要使用到;
  3. .proto文件在tron的github库的单独项目里,名为protocal。使用protobuf php版的官方指引里的方法,生成对应的php文件。一共有两个目录,一个是core,一个是apicore目录可以顺利生成api需要下载安装官方的东西,在install-googleapis.sh这个文件里有写,其中go的部分暂时没用到,直接执行下面获取jar包的部分就可以
  4. 还有一个名为install-protobuf.sh的文件,这里是安装一些依赖的proto文件。因为有些proto文件会引用一些标准的proto文件Make install之后,需要把安装位置的protobuf目录复制到protocol项目目录的google目录下,然后按下面的命令生成php文件。不能直接引用前面make install的位置,会因为命名空间的问题在导致项目中无法使用。
  5. 使用

 

protoc --proto_path=./ --php_out=./ --grpc_out=./ --plugin=protoc-gen-grpc=./../../bins/opt/grpc_php_plugin PATH/xxx.proto

 

 

这样的命令来将.proto文件生成对应的类。会生成两个目录,一个是Protocal,一个是GPBMetadata,这两个文件都需要引入rpc请求客户端项目中

 

注意需要检查一下protocol项目中.proto文件里有import标准.proto文件的句子,比如引用google的标准库里的proto。对于这些proto,需要单独再执行一次protoc,生成相应的类。不然在运行时,会出现类找不到的问题。

 

protoc--proto_path=./ --php_out=./ --grpc_out=./--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugingoogle/api/annotations.proto

 

protoc--proto_path=./ --php_out=./ --grpc_out=./--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin google/api/http.proto

 

protoc --proto_path=./ --php_out=./ --grpc_out=./--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin google/protobuf/any.proto

 

 

  1. 在引用的时候,可能要根据自己的项目,需要单独写一个load规则,来加载通过上面步骤生成的文件。 
  1. 注意在生成Protocol与GPBMetadata目录里的php文件之外,在使用google的内建proto时,会在google目录里对应的目录里也生成一些php文件,需要把这些php文件,使用相应的命名空间,引用到项目中。比如,在生成http.php文件时,就会在google/api目录下也生成一个http.php。这两个文件是不同的,需要分别引用。

如果是使用java

如果是使用java,按官方文档描述,说不需要指定--plugin这个参数,只要指定--java_out就可以在目录里生成相应的类文件。其它跟php类似实际上这里是没写清楚。

protoc-I=./ --java_out=./java/ google/protobuf/any.proto

 

实际使用的时候发现缺少客户端类,查博客发现需要单独编译一个plugin出来

https://github.com/grpc/grpc-java/blob/master/COMPILING.md

会在compiler/build/exe/java_plugin目录下生成protoc-gen-grpc-java

 

protoc--plugin=protoc-gen-grpc-java=/YOUR_PATH/grpc-java/compiler/build/exe/java_plugin/protoc-gen-grpc-java--grpc-java_out=./java/ ./api/api.proto

 

执行上面的命令,会在java的对应目录下生成一些xxxGrpc.java文件

 

使用的时候,生成的xxxGrpc.java文件依赖io.grpc包,从Maven里可以找到。旧版本不可以,这里对3.5.1的protoc,使用io.grpc的1.12.0版本是可以的

 

有些文档说可以在IDE里通过配置maven的配置文件plugin来自动生成所需的java类。实测了一下并不成功,可能是有些步骤没考虑到,实际使用的时候不建议使用这个方法

 

运行时有可能会报MethodNotFoundException,这个是由于默认加载的guava版本太低(13.0),修改maven显式引入更高的版本(25-jre)ok了






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
使用WebSocket和protobuf与设备连接通信的具体步骤如下: 1.定义protobuf格式的消息类 首先,需要定义protobuf格式的消息类。这个类将被用于序列化和反序列化数据。例如,可以定义一个名为DeviceMessage的类: ```protobuf syntax = "proto3"; package com.example.proto; message DeviceMessage { int32 id = 1; string name = 2; bool enabled = 3; } ``` 2.使用WebSocket与设备建立连接 使用WebSocket与设备建立连接。在Java中,可以使用Spring框架提供的WebSocket支持来实现WebSocket通信。例如,可以定义一个名为DeviceWebSocketHandler的类: ```java @Component public class DeviceWebSocketHandler extends TextWebSocketHandler { @Override public void handleTextMessage(WebSocketSession session, TextMessage message) { // 处理接收到的消息 String payload = message.getPayload(); System.out.println("Received message: " + payload); } @Override public void afterConnectionEstablished(WebSocketSession session) { // 建立连接后的处理 System.out.println("Connection established"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { // 关闭连接后的处理 System.out.println("Connection closed"); } } ``` 3.将数据序列化为protobuf格式并发送 在处理接收到的消息时,可以将数据反序列化为protobuf格式。在发送消息时,需要将数据序列化为protobuf格式。例如,可以定义一个名为DeviceService的类: ```java @Service public class DeviceService { private final DeviceWebSocketHandler webSocketHandler; @Autowired public DeviceService(DeviceWebSocketHandler webSocketHandler) { this.webSocketHandler = webSocketHandler; } public void sendDeviceMessage(DeviceMessage message) throws Exception { byte[] data = message.toByteArray(); String payload = Base64.getEncoder().encodeToString(data); TextMessage textMessage = new TextMessage(payload); webSocketHandler.handleTextMessage(textMessage); } } ``` 4.在客户端接收数据并反序列化为protobuf格式 在处理接收到的消息时,可以将数据反序列化为protobuf格式。例如,可以定义一个名为DeviceClient的类: ```java public class DeviceClient extends WebSocketClient { private final DeviceMessageHandler messageHandler; public DeviceClient(String url, DeviceMessageHandler messageHandler) { super(URI.create(url)); this.messageHandler = messageHandler; } @Override public void onOpen(ServerHandshake handshakedata) { System.out.println("Connection established"); } @Override public void onClose(int code, String reason, boolean remote) { System.out.println("Connection closed"); } @Override public void onMessage(String message) { byte[] data = Base64.getDecoder().decode(message); try { DeviceMessage deviceMessage = DeviceMessage.parseFrom(data); messageHandler.handleMessage(deviceMessage); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } @Override public void onError(Exception ex) { ex.printStackTrace(); } public static void main(String[] args) throws Exception { DeviceClient client = new DeviceClient("ws://localhost:8080/devices", new DeviceMessageHandler() { @Override public void handleMessage(DeviceMessage message) { System.out.println("Received message: " + message); } }); client.connect(); DeviceMessage deviceMessage = DeviceMessage.newBuilder() .setId(1) .setName("Device 1") .setEnabled(true) .build(); byte[] data = deviceMessage.toByteArray(); String payload = Base64.getEncoder().encodeToString(data); client.send(payload); } public interface DeviceMessageHandler { void handleMessage(DeviceMessage message); } } ``` 以上就是使用WebSocket和protobuf与设备连接通信的基本步骤。具体实现可能会因为业务场景的不同而有所不同,但是大致流程是相似的。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LeetJoe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值