Protobuf网络上使用嵌套数据(C+;+;到C)反序列化的导线类型异常无效 我已经得到了一个C++应用程序(一个内置的可执行代码和现在不生成的源代码),它使用生成的PROTO类发送原始BuffF消息。我使用了它用来生成类的相同的.proto文件,并在一个C#应用程序中生成了相关的类。其目的是能够使用C#端的protobuf net在这些应用程序之间接收和发送消息。请注意,两者都使用proto2格式

Protobuf网络上使用嵌套数据(C+;+;到C)反序列化的导线类型异常无效 我已经得到了一个C++应用程序(一个内置的可执行代码和现在不生成的源代码),它使用生成的PROTO类发送原始BuffF消息。我使用了它用来生成类的相同的.proto文件,并在一个C#应用程序中生成了相关的类。其目的是能够使用C#端的protobuf net在这些应用程序之间接收和发送消息。请注意,两者都使用proto2格式,c#,c++,deserialization,protocol-buffers,protobuf-net,C#,C++,Deserialization,Protocol Buffers,Protobuf Net,只能成功序列化和反序列化具有简单类型(例如int)成员的消息。但是,将具有嵌套消息类型的消息反序列化到我的C#应用程序中似乎存在问题,例如 message Outer { optional Inner = 1; } message Inner { optional float f = 1; } 接收到的“外部”类型的消息将无法通过以下方式在C#中反序列化: 序列化程序。反序列化(新内存流(msg));//msg是一个字节[] 给出了一个“无效导线类型异常”。我跟踪了链接,但

只能成功序列化和反序列化具有简单类型(例如int)成员的消息。但是,将具有嵌套消息类型的消息反序列化到我的C#应用程序中似乎存在问题,例如

message Outer {
    optional Inner = 1;
}

message Inner {
    optional float f = 1;
}
接收到的“外部”类型的消息将无法通过以下方式在C#中反序列化:

序列化程序。反序列化(新内存流(msg));//msg是一个字节[]
给出了一个“无效导线类型异常”。我跟踪了链接,但查看了这些答案后,我没有发现任何与我的情况相关的明显信息。我95%确定源和目标生成的类是相同的,数据没有损坏,并且我正在反序列化到正确的类型

我能正确地反序列化这些嵌套类型吗?是否有兼容性问题与类生成的方式(以及它是如何序列化)在C++应用程序中使用CytoBuf net?
是一个示例项目(针对.NET Core 3.1在VS 2019中制作),它将重现该问题。

我的传入数据中有大约50个额外字节的“stuff”(即不是消息头),它们不符合定义的消息格式,因此数据基本上已损坏。从字节流中很难看出这一点;我在C#端序列化的消息的长度与我从wireshark中读取的消息的字节长度不同,这就泄露了这一点。然后,我查看了这些字节,并以某种方式找到了与序列化消息等效的字节

为什么传入消息中有额外的“东西”是另一回事,但这是一个实现细节,所以我会考虑这个问题。

如果在类似情况下它对任何人都有帮助,我做了一个小测试循环,不断尝试逐字节反序列化,直到它起作用为止(可以改进,但现在起作用):

var rawBytes=msg.GetBytes();//原始传入消息
布尔成功=假;
外型外型;
而(!成功)
{
尝试
{
rawBytes=rawBytes.Skip(1).ToArray();
outer=ProtoBuf.Serializer.Deserialize(新内存流(rawBytes));
如果(外部?.InnerMsg!=null)
成功=真实;
}
捕获(例外e)
{
//导线类型异常:忽略它,不在乎
}
}

我将从“同一”实例的两种语言生成字节数组,并对它们进行比较。由于协议非常简单,因此应该可以看出区别所在。@Voo比较了一个简单类型的消息,字节是相同的。我只有一个内置版本的C++应用程序和源代码,因为缺少依赖性,现在还没有构建。我用wireshark抓取了数据包,并将其转换为一个字节[]进行比较。但是,因为我不知道嵌套类型的传入数据应该具有什么值,所以我不知道这是否是一个有用的比较。我会四处挖掘,看看是否能找到数据。FWIW,这应该行得通,IMHO。这似乎是protobuf应该能够做到的核心。你能发布一个完整的、独立的测试用例吗?@500 InternalServerError我不知道你的意思;你想自己拿着它运行吗?或者你想知道更多关于当前问题的细节吗?是的,如果我们都能尝试你正在尝试的东西,那就太好了。
Serializer.Deserialize<T>(new MemoryStream(msg)); // msg is a byte[]
var rawBytes = msg.GetBytes(); // The raw incoming message
bool success = false;
OuterMsgType outer;
while (!success)
{
    try
    {
        rawBytes = rawBytes.Skip(1).ToArray();
        outer = ProtoBuf.Serializer.Deserialize<OuterMsgType>(new MemoryStream(rawBytes));
        if (outer?.InnerMsg != null)
             success = true;
    }
    catch (Exception e)
    {
        // Wire type exception: Ignore it, don't care
    }
}