从套接字读取消息时如何获取字节序?
Posted
技术标签:
【中文标题】从套接字读取消息时如何获取字节序?【英文标题】:How to get the endianness when reading a message from socket? 【发布时间】:2014-02-13 11:45:53 【问题描述】:我正在使用go
和protocol buffers
。 go
程序将编码的协议缓冲区消息发送到连接到套接字的客户端。现在由于协议缓冲区没有分隔,客户端不知道要从套接字读取多少数据。
我打算在消息前面加上消息长度,一个 32 位整数。因此客户端可以读取 4 个字节,获取长度并读取完整消息。
我可以使用binary
包将整数值放入字节数组中。类似的,
binary.Write(buf, binary.LittleEndian, value)
现在的问题是,write
需要字节顺序,接收端如何知道字节顺序是什么?有没有办法在不指定明确的字节顺序的情况下处理这个问题?
【问题讨论】:
【参考方案1】:约定是network byte order is big endian,但无论如何您的客户端和服务器都必须同意。明确指定字节顺序。
编辑:阅读 Protobuf 文档,为了保持一致性,最好使用 proto.EncodeVarint
和 proto.DecodeVarint
在消息前写入长度。
【讨论】:
谢谢。这是有道理的。【参考方案2】:您应该始终明确定义和记录此类事物的字节顺序(和布局)。在一般通信中,大端直接布局似乎是常态(因此 47 将是 4 个字节,十六进制值为 00 00 00 2F)。但是,您可能需要考虑特定的上下文。例如,如果您已经在谈论 protobuf,您还可以使用“varint”编码格式,在这种情况下 47 是一个单字节:2F - 许多 protobuf 实现将提供预滚动的方法来使用或产生一个 varint(否则,它是 documented here - 但可以总结为 7 位有效负载和连续位,最不重要的 7 位组在前)
【讨论】:
谢谢。varint
有道理.. 将查看 Java API 是否支持生产和使用 varint 的方法
看来我可以使用 CodedInputStream#readRawVarint32()
来解决这个问题。
您对此有何看法:一次读取每个字节,要求 protobuf 解析它,如果失败,继续读取和解析,直到通过。这样我们就不需要在前面加上长度了。你认为这比前缀长度更好吗?
@Appu 无效; protobuf 流未终止(它们被设计为可附加的)。因此,您无法确定有效负载的结束位置。如果你按照你的建议去做,你只会阅读消息的第一个字段。第二个字段将被解释为第二条消息。基本上,“不,你不能那样做”。以上是关于从套接字读取消息时如何获取字节序?的主要内容,如果未能解决你的问题,请参考以下文章