在C#中解析原始协议缓冲区字节流

时间:2013-10-29 00:08:57

标签: c# protocol-buffers protobuf-net

给定协议缓冲区编码Streambyte[]但不了解对象类型本身,我们如何打印消息的骨架?该用例用于调试基于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 个答案:

答案 0 :(得分:3)

首先请注意,google“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;
        }
    }
}