端口号、语言、硬件和网络

本文关键字:网络 硬件 语言 口号 | 更新日期: 2023-09-27 18:04:20

我们知道端序与计算机存储数据的方式有关。大端计算机架构包括IBM 370、摩托罗拉68000和Sun Sparc。小端计算机包括英特尔系列(80486,奔腾等)和VAX。

由于JVM的原因,Java总是Big-Endian。由于协议的原因,网络应该始终是大端的。

  1. C, c++和c#取决于它们运行的计算机?
  2. 由于协议的原因,网络应该始终是大端的。如果我们在发送之前不打电话给tonons和htonl怎么样?如果发送者是intel机器上的c++,那么发送的数据将是Little-endian。对吗?
  3. 所以我们不需要关心端序(调用ntohl和htonl),如果我们知道所有的客户端和服务器将使用具有相同架构的计算机,并将使用相同的程序语言。对吗?

端口号、语言、硬件和网络

  1. 至少对于C和c++来说,是的;端序通常取决于机器(但也可能取决于编译器)。对于c#,我不知道。
  2. 是的,许多网络协议是大端的。如果您不调用htonl,那么您将无法在小端机器上创建有效的数据包。
  3. 所以你应该总是调用htonl等(或在你使用的任何语言中等效)。因为即使你今天有一个同质的环境,几乎可以肯定的是,在未来,这种情况会发生变化。
更具体地说,应该总是在接近接口的地方转换,并在一个地方转换。如果您的代码库中散布着字节顺序转换调用,则很难判断您的代码是否合理。
  1. 计算机间二进制传输的数据依赖于端序。

  2. C、c++和c#对端序没有任何要求和要求。

  3. 网络应遵循协议。这些数字在每个协议输入和输出之后被转换为内部格式。

  4. 在计算机之间传输二进制数据时,无论是存储在文件中还是立即传输,都只需要担心端序

  5. 浮点数也有类似的问题

  6. 许多语言不关心Endianness

严格地说,Java使用与其运行的硬件相同的端序,但是对于JVM用户没有显示,因为您无法在Java中访问原始内存。

  1. 正确,C语言使用当前运行处理器使用的布局。
  2. 正确的。
  3. 无论如何,总是转换为网络字节顺序是一个很好的做法。迟早你会后悔你没有使用按钮(和其他),只是因为它暂时无关紧要。成本通常是最低的,所以除非你有很好的理由不这样做,否则就这样做吧!

用非常抽象的术语来说,只有当您序列化数据时,您必须意识到端序并特定于端序。这有一个非常精确的含义,实际上在某种程度上被c++语言标准所涵盖:

在程序的主体部分,数据来自于某种类型的变量,写为T x;。到目前为止还很便携;你的程序总是做你想做的,你不需要知道x是如何在内部表示的。您知道x的内存从&x开始,长度为sizeof(T)字节,但您不知道其他任何信息。如果你真的想知道,你必须将&xT*转换为unsigned char*

虽然通常禁止强制转换指针(称为"类型双关"),但这种特殊的强制转换是标准明确允许的。将数据从不透明类型T序列化为实际字节流的唯一方法是将转换为字符指针。正是在这个时刻,您必须知道端序(或者更一般地说,表示),因为您必须知道字节流以何种顺序构成T的内部表示。

对于整型,可以不强制转换指针,但接口仍然处于字节流到值的转换阶段:

unsigned char buf[sizeof(unsigned int)];
unsigned int value;
buf[0] = value; buf[1] = value >> 8; buf[2] = value >> 16; /*...*/  // We chose an endianness!
value = buf[0] + (buf[1] << 8) + (buf[2] << 16) + ... ; // ditto

在使用readwrite这样的操作时,你会发现需要将值转换为字节流,反之亦然,这些操作通常与文件、流或套接字相关。

注意,对于整型值,我们永远不需要知道程序本身的端序——我们只需要知道字节流使用的端序!