在 C# 中解析原始协议缓冲区字节流
Posted
技术标签:
【中文标题】在 C# 中解析原始协议缓冲区字节流【英文标题】:Parsing a raw Protocol Buffer byte stream in C# 【发布时间】:2013-10-29 00:08:56 【问题描述】:给定一个编码为Stream
或byte[]
的协议缓冲区,但不知道对象类型本身,我们如何打印消息的骨架?该用例用于调试基于 protobuf 的 IO,用于根本原因分析。
如果有现有的工具可以从二进制文件中解析原始协议缓冲区字节流,那就太好了!另一种方法可能是使用 ProtoBuf.NET 类 ProtoReader()
继续运行,直到我们遇到错误,但 ProtoReader() 的用法尚不清楚。我从下面开始,但找不到关于如何使用 ProtoReader
类来实际执行它的好的文档。该项目的源代码也不是很容易理解......所以希望得到一些提示/帮助
using (var fs = File.OpenRead(filePath))
using (var pr = new ProtoReader(fs, TypeModel.Create(), null))
// Use ProtoReader to march through the bytes
// Printing field number, type, size and payload values/bytes
【问题讨论】:
【参考方案1】:首先,请注意,谷歌“protoc”命令行工具具有尝试反汇编没有架构信息的原始消息的选项。使用 protobuf-net,您可以执行以下操作 - 但我需要强调 没有架构,格式是不明确的:数据类型/格式比“有线类型”(实际编码格式)。这里我只是展示可能的解释,但还有其他方法可以解析相同的数据。
static void WriteTree(ProtoReader reader)
while (reader.ReadFieldHeader() > 0)
Console.WriteLine(reader.FieldNumber);
Console.WriteLine(reader.WireType);
switch (reader.WireType)
case WireType.Variant:
// warning: this appear to be wrong if the
// value was written signed ("zigzag") - to
// read zigzag, add: pr.Hint(WireType.SignedVariant);
Console.WriteLine(reader.ReadInt64());
break;
case WireType.String:
// note: "string" here just means "some bytes"; could
// be UTF-8, could be a BLOB, could be a "packed array",
// or could be sub-object(s); showing UTF-8 for simplicity
Console.WriteLine(reader.ReadString());
break;
case WireType.Fixed32:
// could be an integer, but probably floating point
Console.WriteLine(reader.ReadSingle());
break;
case WireType.Fixed64:
// could be an integer, but probably floating point
Console.WriteLine(reader.ReadDouble());
break;
case WireType.StartGroup:
// one of 2 sub-object formats
var tok = ProtoReader.StartSubItem(reader);
WriteTree(reader);
ProtoReader.EndSubItem(tok, reader);
break;
default:
reader.SkipField();
break;
或在 v3 中:https://***.com/a/64621670/23354
【讨论】:
马克,太好了。鉴于您的经验,您能否建议使用 Google 的protoc
?我只是找不到有关它的文档。我确实使用了--decode_raw
,但不清楚如何将二进制数组传递给它(例如:.bin 文件)...
Failed to parse input.
和 protoc
和以前一样,即使 ProtoBuf 能够很好地读取二进制文件/流。以为我可能缺少某些格式或参数,但现在猜。没关系,我将只使用 ProtoBuf.NET 代码。谢谢!
@user100003 如果您认为数据是子对象,那么您基本上完全使用StartGroup
中显示的相同代码 - 即StartSubItem
, @ 987654329@,EndSubItem
。更正确的方法是将数据获取为byte[]
(ProtoReader.AppendBytes
),然后测试它是否正确解析为(单独)UTF-8 字符串、子留言等以上是关于在 C# 中解析原始协议缓冲区字节流的主要内容,如果未能解决你的问题,请参考以下文章
Java学习笔记6.1.3 字节流 - 字节流缓冲区与缓冲字节流