字节序,语言,硬件和网络

时间:2011-08-03 19:53:11

标签: c# java c++ networking programming-languages

我们知道endian与计算机存储数据的方式有关。大端计算机体系结构包括IBM 370,Motorola 68000和Sun Sparc。小端计算机包括intel系列(80486,pentium等)和VAX。

由于JVM,Java始终是Big-Endian。 由于协议,网络应始终为Big-Endian。

  1. C,C ++和C#depand在他们运行的计算机上?
  2. 由于协议,网络应始终为Big-Endian。如果我们在发送之前不调用htons和htonl怎么样?如果发送者是英特尔计算机上的C ++,则发送的数据将是Little-endian。是不是?
  3. 所以我们不需要关心endian(调用ntohl和htonl),如果我们知道所有客户端和服务器将使用具有相同体系结构的计算机并且将使用相同的程序语言。是不是?

4 个答案:

答案 0 :(得分:8)

  1. 对于C和C ++,至少,是的;字节序通常取决于机器(但也可能取决于编译器)。对于C#,我不知道。
  2. 许多网络协议都是大端的,是的。如果您不致电htonl,那么您将无法在小端机器上创建有效数据包。
  3. 因此,您应该始终调用htonl等等(或者使用您使用的任何语言的等效语句)。因为即使你今天拥有一个同质的环境,几乎可以肯定,将来这种情况会发生变化。
  4. 更具体地说,您应该始终将转换为尽可能靠近界面,并在一个地方 。如果您的代码库中存在遍布字节顺序转换调用,则很难判断您的代码是否合理。

答案 1 :(得分:1)

  1. 二进制计算机之间传输的数据取决于Endian排序。

  2. C,C ++和C#对Endianess没有任何要求或要求。

  3. 网络应遵循协议。在按协议输入和写出数字后,这些数字将转换为内部格式。它们可以是任何内部处理格式。

  4. 在计算机之间传输二进制数据时,只关心Endianess,无论是存储在文件中还是立即传输。

  5. 浮点数遭遇类似问题。

  6. 许多语言都不关心Endianness。

答案 2 :(得分:1)

严格地说Java使用与运行它的硬件相同的endian,但它没有为JVM用户显示,因为你无法访问Java中的原始内存。

  1. 对,C语言使用当前运行的处理器使用的布局。
  2. 正确。
  3. 无论如何总是转换为网络字节顺序是一种好习惯。迟早你会后悔你没有使用htons(和其他人)因为暂时没关系。成本通常是最低的,所以除非你有充分的理由不这样做!

答案 3 :(得分:0)

以非常抽象的术语来说,当您序列化数据时,必须具有字节序感知和特定于字节序的唯一时间。这具有非常精确的含义,实际上在某种程度上由C ++中的语言标准涵盖:

在程序的主要部分中,数据来自某个类型的变量,写为T x;。到目前为止便携;你的程序总是做你想要的,你不需要知道内部如何表示x。您知道x的内存从&x开始,并且sizeof(T)字节长,但您不知道其他任何内容。如果您确实想要查找,则必须将&xT*投射到unsigned char*

虽然一般禁止使用指针(它被称为“类型双关语”),但标准明确允许此特定强制转换。转换为char-pointer是将序列化数据从opaque类型T转换为实际字节流的唯一方法。正是在这个时刻你必须知道字节序(或更一般地说,表示),因为你必须知道字节流构成T的内部表示的顺序。 / p>

对于整数类型,您可以在不转换指针的情况下执行,但接口仍处于从字节流到值的转换:

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等操作时,您会发现需要将值转换为字节流,反之亦然,通常与文件,流或套接字相关联。

注意,对于整数值,我们从不需要知道程序本身的字节顺序 - 我们需要知道字节流使用的字节顺序!