如何将可读protobuf请求转为proto消息 解决gRPC请求400报错及解码问题
Proto定义错误说明与修正
你当前的Proto定义存在2个核心错误:
- Protobuf协议明确保留字段号
0,不允许在消息定义中声明使用,你看到的解码输出里的0: 0属于无Schema解析时的异常输出,大概率是未剥离gRPC帧头、请求数据截断导致的误识别,不需要在Proto中对应定义。 - 你定义的
submit消息中字段16的类型错误,解码输出里16 {表示该字段是嵌套消息类型,而非你写的string类型;字段8下的层级结构如果是可重复项需要加repeated修饰。
修正后的Proto定义
syntax = "proto3"; message SubmitRequest { string pid = 1; string rtext = 2; int32 str = 3; UnknownData7 unknown7 = 7; UnknownData8 unknown8 = 8; UnknownData9 unknown9 = 9; int32 unknown11 = 11; int32 unknown12 = 12; int32 unknown14 = 14; UnknownData16 unknown16 = 16; // 根据你后续完整的解码输出补充内部字段即可 } message UnknownData7 { string auto_data = 9; int32 auto_int = 15; } message UnknownData8 { repeated UnknownData8Item items = 1; } message UnknownData8Item { int32 value = 1; } message UnknownData9 { int32 val1 = 1; int32 val2 = 2; } message UnknownData16 { // 根据完整的解码输出补充对应字段即可 }
PHP代码错误修正
你当前的PHP代码逻辑完全错误,PHP Protobuf库的序列化流程不是传入JSON字符串,而是需要先通过protoc配合PHP插件生成上述Proto对应的类文件,再实例化类赋值后序列化,示例代码如下:
// 首先导入protoc生成的类文件 require 'vendor/autoload.php'; use Your\Namespace\SubmitRequest; use Your\Namespace\UnknownData7; // 其余嵌套类导入省略 $req = new SubmitRequest(); $req->setPid("0x80c2:0x3a2f"); $req->setRtext("this is test"); $req->setStr(5); // 构造嵌套字段赋值示例: $ud7 = new UnknownData7(); $ud7->setAutoData("nG86YfStD4Of9QPB_L_QDg:28441478"); $ud7->setAutoInt(20089); $req->setUnknown7($ud7); // 所有字段赋值完成后序列化 $protobufPayload = $req->serializeToString(); // 再将序列化后的payload加上gRPC帧头后发送请求即可
二进制gRPC/protobuf解码方法
你贴的二进制数据是标准的gRPC请求帧结构,解码步骤如下:
- 先剥离前5字节的gRPC帧头:第1字节是压缩标识,第2-5字节是payload长度
- 根据压缩标识判断是否需要解压:你给出的示例中后续有
\x1f\x8b\x08是gzip压缩的魔术头,需要先做gzip解压得到原始protobuf二进制 - 解码工具首选官方
protoc命令:- 无Proto schema时输出类JSON可读结构:
protoc --decode_raw < 二进制文件路径 - 有Proto schema时输出结构化解析结果:
protoc --decode=SubmitRequest your_proto_file.proto < 二进制文件路径
- 无Proto schema时输出类JSON可读结构:
内容的提问来源于stack exchange,提问作者Tuber Boy
相关产品推荐
相关产品推荐

