0

所以,在过去的几周里,我一直在学习非常简单的网络编程和协议缓冲区。现在,我有一个 Java 客户端和一个 C# 服务器,它们使用协议缓冲区来回通信。一切正常,但要使其在客户端(Java)端工作,我必须创建具有传入消息的确切大小的字节数组,否则解析器会抛出“协议消息包含无效标签(零)"

在做了一些研究之后,我发现我为我的 DatagramPacket 创建的数组(1024 字节)有大量的尾随零(因为我从服务器传入的数据是 27 字节长),这就是为什么我现在,如前所述,必须使用传入数据的确切大小创建数组。

至于问题,有没有办法找出我的 .proto 文件中所有原型“消息”的大小?如果没有某种静态 getSize(),有没有一种方法可以仅通过“消息”中的字段类型来计算?

我现在使用的消息包含 3 个双精度,现在我正在考虑它,但我希望知道发生了什么的人给出肯定的答案,是 27,因为每个双精度 8 字节和每个“标签”1 字节“在每个消息字段上?

4

2 回答 2

0

我相信您的问题在于您的套接字接收代码。有一个尾随零的数组不是问题,但是在接收时,您应该检查接收到的字节数(它是接收调用的返回值),并且只考虑缓冲区数组从开始到“接收到的字节数”的字节数”。

于 2013-08-29T05:57:29.753 回答
0

protobuf 数据中的根对象不是自终止的;它被设计为可附加的(使用 append===merge),所以通常库只是读取数据,直到数据用完。如果您有备用零,它将无法解析下一个字段标题。有两种方法可以解决这个问题:

  • 如果您只想发送一条消息,只需在消息末尾关闭出站套接字即可;客户端应该检测到套接字的结束并相应地进行补偿(注意,除非您使用长度限制的流包装器,否则您仍然不想使用过大的缓冲区)
  • 使用某种“框架”协议;其中最简单的就是简单地在每条消息前面加上该消息中的字节数(请注意,在一般情况下,这个大小不是固定的,但在关闭 3 个双精度的情况下,每个都有一个字段编号的字段标题不大于 16,然后是:它将是 27 个字节);然后,您可以创建正确大小的缓冲区(注意重复的数组分配可能很昂贵),或者更典型的是:使用长度限制的流包装器,或内存支持的内存中流
于 2013-08-29T06:54:09.730 回答