通过Socket发送协议缓冲区数据并确定类

时间:2014-07-03 12:02:31

标签: c++ sockets protocol-buffers

我现在正在使用谷歌协议缓冲区并有一个问题。如果我有多个.proto文件,因此有多个类,是否可以通过套接字发送数据以确定它是哪种类型?

E.g。我有两个类,我们称之为person.proto和adress.proto。现在我通过电汇发送其中一个。接收者如何确定它是人还是地址?

我在C ++中这样做。

我的尝试是在消息周围添加一个框架,其中包含长度和类型。但我想知道是否已经有类型的东西的某种实现,所以我不重新实现现有的东西。

2 个答案:

答案 0 :(得分:2)

是的,这是可能的。 Protobuf使用所谓的message descriptors支持反射。

但是(如另一个答案所述)你需要一个可靠的众所周知的根消息类型。恕我直言,不是引入自己的信息识别机制,而是使用protobufs extension mechanism

以下是我们生产中的样本

package Common.ConfigurationCommands;

message UcpConfiguration
{
     optional uint32 componentIndex = 1;
     optional ConfigCmdStatus configCmdResponseStatus = 2;
     optional string configErrorDescription = 3;

     extensions 100 to max;
}

扩展名如

import "Common/ConfigurationCommands.proto";

message AmplifierConfiguration
{
    extend Common.ConfigurationCommands.UcpConfiguration 
    {
        optional AmplifierConfiguration amplifierConfiguration = 108;
    }
    optional uint32 preemphasis = 1;
}

import "Common/ConfigurationCommands.proto";

message FrontendConfiguration
{
    extend Common.ConfigurationCommands.UcpConfiguration 
    {
        optional FrontendConfiguration frontendConfiguration = 100;
    }
    optional bool frontendActive = 1;
    optional uint32 refInputComponentIndex = 2;

    extensions 100 to max;
}

您可以查看this part of the documentation,了解如何处理C ++代码中的扩展程序。

答案 1 :(得分:1)

无法检测哪个对象被序列化,Protobuf不会这样做。但你可以很容易地使用protobuf处理它:

1)方法:只发送包含类型和字符串主体的消息。对于正文,您将序列化对象,在类型中,您将显示序列化的对象:

类似的东西:

package MyGreatPackage;

message Pack
{
    required bytes packcode = 1;
    //code for data/query
    required bytes  mess = 2;
}

message Data
{
//anything you need to
}

message Query
{
//anything you need to
}

因此,您将始终发送消息包,其中将定义哪个对象完全位于" mess"字段。

2)方法: protobuf允许这种技术在没有包装器的情况下实现相同的功能,请看这里:https://developers.google.com/protocol-buffers/docs/techniques?hl=ru#union

message OneMessage {
  enum Type { FOO = 1; BAR = 2; BAZ = 3; }

  // Identifies which field is filled in.
  required Type type = 1;

  // One of the following will be filled in.
  optional Foo foo = 2;
  optional Bar bar = 3;
  optional Baz baz = 4;
}

因此,您可以将可能发送的所有类设置为可选,并根据所需参数确定其类型。

不过,对我来说,第一个varians似乎更好,选择你喜欢的。