简体   繁体   English

Java协议缓冲区-消息大小

[英]Java Protocol Buffers - Message sizes

So, for the past few weeks I've been learning very simple network programming and protocol buffers. 因此,在过去的几周中,我一直在学习非常简单的网络编程和协议缓冲区。 Right now, I have a Java client and a C# server that are communicating back and forth using the protocol buffers. 现在,我有一个Java客户端和一个C#服务器,它们正在使用协议缓冲区来回通信。 It's all working fine, but to make it work on the client (Java) side I had to create my byte array with the exact size of the incoming message or else the parser would throw an error of "Protocol message contained an invalid tag (zero)" 一切正常,但是要使其在客户端(Java)端正常工作,我必须使用传入消息的确切大小创建我的字节数组,否则解析器将抛出错误“协议消息包含无效标记(零)”

After doing some research, I came to find out that the array I had created (1024bytes) for my DatagramPacket had tons of trailing zeros (since my incoming data from the server was 27bytes long), and that's why I now, as previously mentioned, have to create the array with the exact size of the incoming data. 经过研究后,我发现为DatagramPacket创建的数组(1024字节)具有成千上万的尾随零(因为从服务器传入的数据为27字节长),这就是为什么我现在如前所述,必须使用传入数据的确切大小创建数组。

As for the question, is there any way to find out the size of all of my proto "messages" in my .proto files? 至于问题,是否有办法找出.proto文件中所有原型“消息”的大小? If there isn't some sort of static getSize(), is there a way I can calculate that just by the types of fields I have within the "message"? 如果没有某种静态的getSize(),有没有一种方法可以仅根据“消息”中的字段类型来计算?

My message I'm using right now contains 3 doubles, and now that I'm thinking about it, but I want a for sure answer from someone who knows what's going on, is it 27 because 8bytes per double and the 1byte per "tag" on each message field? 我正在使用的消息现在包含3个double,现在我正在考虑它,但是我想肯定知道发生了什么事的人给出的答案是27,因为每双8个字节,每个“标记1个字节”在每个消息字段上?

I believe your problem lies in your socket receive code. 我相信您的问题出在您的套接字接收代码上。 Having an array with trailing zeroes is not a problem, but when receiving you should check the number of bytes received (it is the return value of a receive call) and only consider the bytes of the buffer array from the beginning up to "bytes received". 具有尾随零的数组不是问题,但是在接收时,您应该检查接收到的字节数(这是接收调用的返回值),并且仅考虑缓冲区数组的字节,从开始到“收到的字节” ”。

The root object in protobuf data is not self-terminating; protobuf数据中的根对象不是自终止的; it is designed to be appendable (with append===merge), so normally the library simply reads until it runs out of data. 它被设计为可附加的(带有append === merge),因此通常该库只读取数据,直到用完为止。 If you have spare zeros, it will fail to parse the next field header. 如果您有备用零,它将无法解析下一个字段标头。 There are two ways of addressing this: 有两种解决方法:

  • if you only want to send one message, simply close the outbound socket at the end of you message; 如果只想发送一条消息,只需在消息末尾关闭出站套接字; the client should detect the end of the socket and compensate accordingly (note, you still don't want to use an oversized buffer unless you are using a length-limited stream wrapper) 客户端应该检测套接字的末尾并进行相应的补偿(请注意,除非您使用的是长度受限的流包装器,否则您仍然不希望使用过大的缓冲区)
  • use some kind of "framing" protocol; 使用某种“成帧”协议; the simplest of which is simply to prefix each message with the number of bytes in that message (note that in the general case this size is not fixed, but in the case off 3 doubles, each with a field-header of a field-number no-greater-than 16, then yes: it will be 27 bytes); 最简单的方法是简单地为每个消息加上该消息中的字节数作为前缀(请注意,在一般情况下,此大小不是固定的,但在3倍的情况下,每个长度都带有一个字段号的字段头大于16,然后是:将为27个字节); you would then either create the buffer the right size (noting that repeated array allocations can be expensive), or more typically: use a length-limited stream wrapper, or a memory-backed in-memory stream 然后,您将创建合适大小的缓冲区(请注意重复的数组分配可能会很昂贵),或更典型的做法是:使用长度受限的流包装器或内存支持的内存中流

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM