问题描述
我试图知道我在我的 tcp 套接字中得到了什么包,所以我使用了 protobuf.但是当我 SerializeToString
我的第一个 protobuf 类时,另一个 protobuf 类的 ParseFromString
方法返回 true.
I tried to know what package I got in my tcp socket, so I use protobuf.But when I SerializeToString
my first protobuf class, the ParseFromString
method of an other protobuf class returns true.
两个类是不同的
这是我的 .proto
syntax = "proto3";
package protobuf;
message Message
{
string content = 1;
}
message Player
{
int32 id = 1;
string name = 2;
}
这是我的 C++ 代码
Here is my c++ code
auto messageProto = new protobuf::Message;
messageProto->set_content("Hello");
std::string data;
messageProto->SerializeToString(&data);
protobuf::Player player;
if (player.ParseFromString(data))
{
qDebug() << "parse player";
}
protobuf::Message message2;
if (message2.ParseFromString(data))
{
qDebug() << "parse message";
}
输出:
parse player
parse message
为什么?
推荐答案
我推荐的多个不同payload的解决方案:
My recommended solution to the problem of multiple different payloads:
syntax = "proto3";
package protobuf;
message RenameMe // the outer payload wrapper
{
oneof payload
{
Foo foo = 1;
Bar bar = 2;
}
}
message Foo // one type of content
{
string content = 1;
}
message Bar // another type of content
{
int32 id = 1;
string name = 2;
}
现在您可以将所有内容反序列化为 RenameMe
(命名很难!)并检查 payload
区分联合枚举以了解您应该如何解释数据.然后分别访问 foo
或 bar
.
Now you can just deserialize everything as a RenameMe
(naming is hard!) and check the payload
discriminated union enum to see how you should interpret the data. Then just access foo
or bar
respectively.
这种方法清晰、显而易见,并且可以轻松有效地扩展到其他消息类型.在许多编程语言中,可以使用 switch
来实现测试.这种风格也适用于某些环境中的多态性 - 例如,在 C# 中,protobuf-net 可以通过以下方式进行序列化/反序列化:
This approach is clear, obvious, and readily and effectively extensible into additional message types. The testing can be implemented with switch
in many programming languages. This style also works well with polymorphism in some environments - for example, in C# with protobuf-net that could be serialized/deserialized with:
[ProtoContract, ProtoInclude(1, typeof(Foo)), ProtoInclude(2, typeof(Bar))]
abstract class RenameMe {}
[ProtoContract]
class Foo : RenameMe {
[ProtoMember(1)] public string Content {get;set;}
}
[ProtoContract]
class Bar : RenameMe {
[ProtoMember(1)] public int Id {get;set;}
[ProtoMember(2)] public string Name {get;set;}
}
这篇关于为什么我的 Protobuf 类可以解析由其他 Protobuf 类序列化的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!