0

我正在阅读Google Protocol Buffers。我想知道我可以Serialize C++ object通过网络将它发送到 Java 服务器并Deserialize在那里java检查这些字段。

相反,我想将任何语言的对象发送到 Java Server。并在那里反序列化它。

假设以下是我的.proto文件

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

我在上面运行protoc并创建了一个C++对象。基本上现在我想将序列化流发送到java服务器。

在java端我可以deserialized流,这样我就可以找出3流中的字段及其各自的字段name, type, and value

4

3 回答 3

2

在java端我可以反序列化流,以便我可以找出流中有3个字段及其各自的name, type, 和value

您需要提前了解架构。首先,protobuf不传输名称;它用作标识符的只是每个字段的数字键(1,在您23示例中)。其次,它没有明确指定类型;protobuf 中只有很少的线类型(varint、32 位、64 位、长度前缀、组);实际的数据类型映射到那些,但你不能在没有模式的情况下明确解码数据

  • varint 是“某种形式的整数”,但可以是有符号、无符号或“之字形”(允许对小幅度负数进行廉价编码),并且可以用于表示任何宽度的数据(64 位、32 位、 ETC)
  • 32 位可以是整数,但可以是有符号或无符号的 - 也可以是 32 位浮点数
  • 64 位可以是整数,但可以是有符号或无符号的 - 也可以是 64 位浮点数
  • 长度前缀可以是 UTF-8 字符串、序列或原始字节(没有任何特殊含义)、repeated某些原始类型(整数、浮点等)的“打包”值集,或者可以是结构化子protobuf 格式的消息
  • 团体 - 万岁!这始终是明确的!这只能意味着一件事;但是一件事在很大程度上被谷歌弃用了:(

所以从根本上说:你需要模式。编码数据不包括您想要的。这样做是为了避免不必要的空间——如果协议假设编码器和解码器都知道消息的含义,那么需要发送的信息就会少得多。

但是请注意,即使存在不期望的字段,所包含的信息也足以安全地往返消息如果您只需要重新编码以将其传递/返回,则无需知道名称或类型。

可以做的是使用解析器 API 扫描数据以显示有三个字段,字段 1 是 varint,字段 2 是长度前缀,字段 3 是长度前缀。您可以对除此之外的数据进行有根据的猜测(例如,您可以查看 UTF-8 解码是否产生看起来大致类似于文本的内容,并验证 UTF-8 编码是否会返回原始字节;如果确实如此,它可能是一个字符串)

于 2013-06-13T08:30:41.810 回答
1

我可以序列化 C++ 对象并将其在线发送到 Java 服务器并在 Java 中反序列化并内省这些字段。

是的,这正是 protobuf 的目标。

序列化以任何支持的语言开发的应用程序中的数据,并反序列化以任何支持的语言开发的应用程序中的数据。序列化和反序列化语言可以相同,也可以不同。

请记住,协议缓冲区不是自我描述的,因此应用程序的双方都需要从.proto文件生成序列化器/反序列化器。

于 2013-06-13T08:15:04.657 回答
1

简而言之:是的,你可以。

您将需要创建 .proto 文件来定义您要共享的数据结构。通过使用Google Protocol Buffers编译器,您可以为您的结构JavaC++(以及您能想到的几乎任何其他语言)生成接口和(反)序列化代码。

要通过网络传输数据,您可以使用例如ZeroMQJava ,它是一个极其通用的通信框架,它还支持大量不同语言的 API ,其中包括C++.

有关详细信息,请参阅此问题。

于 2013-06-13T08:16:31.097 回答