【问题标题】:Parsing a raw Protocol Buffer byte stream in C#在 C# 中解析原始协议缓冲区字节流
【发布时间】:2013-10-29 00:08:56
【问题描述】:

给定一个编码为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
    }
}

【问题讨论】:

    标签: c# protocol-buffers protobuf-net


    【解决方案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://stackoverflow.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 字符串、子留言等
    猜你喜欢
    • 1970-01-01
    • 2021-12-19
    • 2012-07-13
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 2023-03-13
    相关资源
    最近更新 更多