我想找到一种方法将二进制protobuf消息转换为包含数据的人类可读描述,而不使用.proto文件.
背景是我有一条.proto消息,它被Android上的解析器拒绝,但它并不完全清楚原因.我可以手工完成这个消息,但这很乏味.
我尝试过protoc --decode_raw,但它只是给出错误"无法解析输入.".我谷歌希望/期望有人会做一个很好的网络实用程序,可能会做到这一点,但没有找到任何明显的东西.
我只是希望获得一些输出:
field 1: varint: 128
field 4: string: "foo"
Run Code Online (Sandbox Code Playgroud)
任何正确方向的指针都是最受欢迎的!
anq*_*anq 30
对于后代:Google的协议缓冲工具可以解码原始缓冲区.
只需将未知缓冲区发送给它并传递--decode_raw标志
$ cat has_no_proto.buff | protoc --decode_raw
2 {
2: "Error retrieving information from server. [RH-02]"
}
Run Code Online (Sandbox Code Playgroud)
所以这是一条消息,其中字段2设置为嵌入消息,而消息又将其第二个字段设置为字符串,告诉我我很生气.
类型信息不明确(看起来它会尝试将所有二进制数据显示为字符串 - 但是满足了对varint/string/submessage区分的要求).
eri*_*ers 11
正如Michel de Ruiter的回答所述,你的protobuf消息可能有一个长度前缀.假设确实如此,这个答案应该有所帮助.
(注意:对于下面的大多数命令,我假设你的protobuf消息存储在一个名为的文件中input.)
protoc --decode_raw+ dd单个消息:如果它只是一条消息,那么你确实可以利用protoc --decode_raw,但你需要首先剥离长度前缀头.假设标头长度为4个字节,您可以使用dd剥离标头input,然后将输出输入protoc.
dd bs=1 skip=4 if=input 2>/dev/null | protoc --decode_raw
Run Code Online (Sandbox Code Playgroud)
protoc-decode-lenprefix --decode_raw 对于单个消息:我还编写了一个脚本来自动处理标题剥离:
protoc-decode-lenprefix --decode_raw < input
Run Code Online (Sandbox Code Playgroud)
这个脚本只是一个包装器protoc --decode_raw,但处理解析长度前缀头然后调用protoc.
现在,在这种情况下,这个脚本并不是非常有用,因为我们可以使用dd上面的技巧来删除标题.但是,假设我们有一个数据流(例如,文件或TCP流),其中包含多个带有长度前缀标题的消息....
protoc-decode-lenprefix --decode_raw 对于消息流:假设input包含多个由长度前缀标题框起的protobuf消息,而不是输入文件中的单个protobuf消息.在这种情况下,它不可能只使用dd技巧,因为您需要实际读取length-prefix标头的内容以确定流中后续消息的长度,以及下一个标头+消息前面有多少字节.因此,您可以protoc-decode-lenprefix再次使用,而不是担心所有这些:
protoc-decode-lenprefix --decode_raw < input
Run Code Online (Sandbox Code Playgroud)
protoc-decode-lenprefix --decode ... foo.proto 用于消息流此脚本还可用于完全解码长度前缀的消息(而不仅仅是"原始解码"消息).它假定您可以访问.proto定义protobuf消息的文件,就像包装protoc命令一样.调用语法与protoc --decode.相同.例如,使用dd技巧protoc --decode,以及作为Mesos task.info文件的输入,语法如下所示:
dd bs=1 skip=4 if=task.info 2>/dev/null | \
protoc --decode mesos.internal.Task \
-I MESOS_CODE/src -I MESOS_CODE/include \
MESOS_CODE/src/messages/messages.proto
Run Code Online (Sandbox Code Playgroud)
使用时参数相同 protoc-decode-lenprefix
cat task.info | \
protoc-decode-lenprefix --decode mesos.internal.Task \
-I MESOS_CODE/src -I MESOS_CODE/include \
MESOS_CODE/src/messages/messages.proto
Run Code Online (Sandbox Code Playgroud)
如果您碰巧有一个包含(多个?)长度前缀的 protobuf消息的二进制文件protoc ??decode_raw < file,由于长度前缀,无法解析它.一个简单的方法是将文件拆分为连续的消息,然后将每个消息转换为protoc.
我的看法:
var fs = File.OpenRead(filename));
var buffer = new byte[4096];
int size;
for (int part = 1; Serializer.TryReadLengthPrefix(fs, PrefixStyle.Base128, out size); part++) {
long startPosition = fs.Position;
using (var writer = File.OpenWrite(string.Format("{0}[{1}].pb", filename, part))) {
for (int bytesToRead = size; bytesToRead > 0; ) {
int bytesRead = fs.Read(buffer, 0, Math.Min(bytesToRead, buffer.Length));
bytesToRead -= bytesRead;
if (bytesRead <= 0) // End of file.
break;
writer.Write(buffer, 0, bytesRead);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以尝试强制通过wireshark插件,或者您可以借用某些实现的"读者"部分(例如,我知道如何在C#中执行此操作,但我怀疑这就是您的意思).
但是,要小心 - 协议缓冲区中的字符串并不真正意味着"字符串" - 它可能是:
| 归档时间: |
|
| 查看次数: |
23515 次 |
| 最近记录: |