【问题标题】:Google Protocol Buffers, how to handle multiple message-Types?Google Protocol Buffers,如何处理多种消息类型?
【发布时间】:2014-12-02 21:52:42
【问题描述】:

是否可以获得序列化的Protocol Buffer消息的Type?

我有这个例子

option java_outer_classname="ProtoUser";

message User {
    required int32  id = 1; 
    required string name = 2;
    required string firstname = 3;
    required string lastname = 4;
    required string ssn= 5; 
}

message Address {
    required int32 id = 1;
    required string country = 2 [default = "US"];; 
    optional string state = 3;
    optional string city = 4;
    optional string street = 5;
    optional string zip = 6;
}

在 Java 中我有这段代码

Address addr = ProtoUser.Address.newBuilder().setCity("Weston").setCountry("USA").setId(1).setState("FL").setStreet("123 Lakeshore").setZip("90210")
            .build();

    User user = ProtoUser.User.newBuilder().setId(1).setFirstname("Luis").setLastname("Atencio").setName("luisat").setSsn("555-555-5555").build();

if(....){
    FileOutputStream output = new FileOutputStream("out1.ser");
    user.writeTo(output);
    output.close();
}else{
    FileOutputStream output = new FileOutputStream("out1.ser");
    addr.writeTo(output);
    output.close();
}

现在,我可以确定文件包含地址还是用户?处理多个消息类型的常用方法是什么?如何确定我收到了哪种消息类型?

【问题讨论】:

    标签: java protocol-buffers


    【解决方案1】:

    我们无法确定文件是否包含地址或用户。因为数据中没有编码类型信息。

    要处理多个消息类型,您可以使用如下元数据:

    • 文件名的扩展名
    • HTTP 中的标头
    • 帧基流协议中的特定帧头
    • ...

    【讨论】:

    • 好的,这只是一个例子。稍后我将通过 TCP 和 Unix 套接字发送序列化字符串。可能类似于发送 'CommandX;'+serializedString 一个好的解决方案?
    • 是的。将一些元数据放在帧的头部来描述下面的payload。
    • @user2071938 您可以将所有消息包装在一个公共容器消息中(全部 optional 或使用新的 oneof 联合结构:developers.google.com/protocol-buffers/docs/proto#oneof) - 这与在protobuf 级别。
    • 同意@zapl。 :-)
    • 另请参阅文档的这一部分,尽管它显然尚未更新以利用 2.6.0 中的新 oneof 功能:developers.google.com/protocol-buffers/docs/techniques#union
    【解决方案2】:

    无论你是:

    1. 在文件结尾包含地址或名称的信息(如果文件一次只包含一种类型)
    2. 以序列化形式显式指定数据包的类型,即添加一个字段required int32 type并从该字段中推断出类型。 (如果两种类型同时包含在一个文件中)
    3. 设计一种明确包含此信息并包装协议缓冲区的特定外部消息格式。

    无论哪种合适,如果您将它们多路复用到一个通道上(通过选择相同的文件结尾来实现),您必须在收到它们时再次将它们多路分解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      相关资源
      最近更新 更多