【问题标题】:How to get the endianness when reading a message from socket?从套接字读取消息时如何获取字节序?
【发布时间】:2014-02-13 11:45:53
【问题描述】:

我正在使用goprotocol buffersgo 程序将编码的协议缓冲区消息发送到连接到套接字的客户端。现在由于协议缓冲区没有分隔,客户端不知道要从套接字读取多少数据。

我打算在消息前面加上消息长度,一个 32 位整数。因此客户端可以读取 4 个字节,获取长度并读取完整消息。

我可以使用binary 包将整数值放入字节数组中。类似的,

binary.Write(buf, binary.LittleEndian, value)

现在的问题是,write 需要字节顺序,接收端如何知道字节顺序是什么?有没有办法在不指定明确的字节顺序的情况下处理这个问题?

【问题讨论】:

    标签: sockets networking encoding go protocol-buffers


    【解决方案1】:

    约定是network byte order is big endian,但无论如何您的客户端和服务器都必须同意。明确指定字节顺序。

    编辑:阅读 Protobuf 文档,为了保持一致性,最好使用 proto.EncodeVarintproto.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 流未终止(它们被设计为可附加的)。因此,您无法确定有效负载的结束位置。如果你按照你的建议去做,你只会阅读消息的第一个字段。第二个字段将被解释为第二条消息。基本上,“不,你不能那样做”。
    猜你喜欢
    • 2015-01-28
    • 2016-05-04
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 2016-06-28
    • 1970-01-01
    相关资源
    最近更新 更多