【问题标题】:Should I think about Network Byte Order?我应该考虑网络字节顺序吗?
【发布时间】:2017-09-06 08:50:49
【问题描述】:

我无法理解“网络字节顺序”的概念。我已阅读 Network byte order and endianness issues,但仍然无法阅读。
现在,我对两台计算机之间通过 TCP 套接字进行的通信进行了正式的网络协议描述。这是短语“...使用 little-endian 字节顺序”。但是标准的网络字节顺序是大端的。

我是否应该考虑字节顺序,如果在网络的两侧都完全定义了字节顺序,并且我写了,粗略地说,void*size?网络如何“知道”我的数据?浮点类型呢?

例如,我是否不能侧写:

stream.setDevice(tcpSocket);
stream.setByteOrder(QDataStream::LittleEndian);
...

struct SomeType
{
    int32_t a;
    int32_t b;
    double c;

    friend QDataStream& operator << (
        QDataStream& stream, const SomeType& x)
    {   
        stream << x.a
            << x.b
            << x.c;

        return stream;
    }        
};

或者可能只是:

SomeType x;
tcpSocket.write(&x, size); // If known a byte order and a data structure alignment on both sides

【问题讨论】:

  • 您计算机中的“网络”或网络堆栈对您传输的数据一无所知,它只是来回传递二进制 blob 序列。当您必须将数据解释为您的程序可以处理的东西时,问题就出现在您的程序中。如果一个 big-endian 系统将未经修改的 int 发送到另一个恰好是 little-endian 的系统,那么接收者会认为接收到的 int 值不是发送的。
  • @Someprogrammerdude ,我可以在我的示例中不考虑这一点(如果知道主机端的字节顺序和数据结构对齐)?
  • @VladimirBershov 你可以,但有一天这个错误会成为一个问题。在任何情况下,您都会看到使用压缩成帧协议的性能和维护优势。 google 的协议缓冲区就是这样一种免费提供的协议。
  • 您的代码在具有不同架构的 2 台机器(例如 x86 little endian 和 arm big endian)上运行时会立即中断。两种变体,因为ints 将有不同的表示。第二个版本甚至可能在不同的编译器版本之间中断,因为他们可能对结构布局(对齐等)有不同的理解。
  • @VladimirBershov 这并不能解决当字节序列 0x00000001 通过网络传输时机器可能将其解释为 1 而另一个解释为 2^24 的问题。避免这种情况的唯一方法是使用适当的序列化,它独立于平台工作。

标签: c++ qt tcp network-programming endianness


【解决方案1】:

32 位值表示为 little-endian(intel 等):

address offset 0 1 2 3 bits 0-7 bits 8-15 bits 16-23 bits 24-31


并以网络字节序或大端序(摩托罗拉 cpus 等)表示:

address offset 0 1 2 3 bits 24-31 bits 16-23 bits 8-15 bits 0-7


取决于您第一次学习编写机器代码的架构(如果您这样做了),其中一种对您来说比另一种更有意义。对于几乎所有 45 岁以下的人来说,它将是 little-endian,这与网络字节顺序相反。

如果您像我一样学会了在 Texas TMS9900 架构上编写机器代码,那就更令人困惑了,因为在 texas-land 中,位 0 是最重要的位 (!)


更新:

一般来说,最好以一种独立于硬件或编译器实现选择,甚至是语言的方式对线路上的数据进行编码。

以下是来自 google 协议缓冲区的此类编码示例:

https://developers.google.com/protocol-buffers/docs/encoding

这里的优点是:

  1. 通常传输的流量更少,因此网络速度更快

  2. 连接的每一端都将理解数据,无论硬件、编译器版本,甚至是语言。

【讨论】:

  • 但是我的情况呢 - 如果知道(并明确定义)字节顺序和主机端的数据结构对齐?
  • @VladimirBershov 这会将您的代码绑定到一个特定的硬件。硬件随时间而变化。你还希望你的代码在 10 年后还能工作吗?
  • 但是如果我将int s 更改为int32_t?而且在任何情况下,浮点值都没有解决方案
  • @VladimirBershov 查看我的更新。这就是谷歌的做法。我在我的代码中遵循他们的示例,因此我的系统可以由用任何语言编写的组件构建。这在您开始扩展解决方案时很有帮助。
  • ...感谢您推荐协议缓冲区。现在看起来是最好的解决方案。无论如何,如果我们从全局来看这个问题,我相信现在考虑网络字节顺序是不可接受的
【解决方案2】:

TCP 套接字只是一个字节流,根本不关心您发送的数据的字节顺序。因此,对于您自己的私有网络协议,您可以使用您喜欢的任何字节顺序。如果使用该协议的所有计算机都具有相同的自然字节顺序,那么将其用作序列化顺序可能是一个好主意,因为这允许您编写像第二个示例一样的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多