端口号、语言、硬件和网络
本文关键字:网络 硬件 语言 口号 | 更新日期: 2023-09-27 18:04:20
我们知道端序与计算机存储数据的方式有关。大端计算机架构包括IBM 370、摩托罗拉68000和Sun Sparc。小端计算机包括英特尔系列(80486,奔腾等)和VAX。
由于JVM的原因,Java总是Big-Endian。由于协议的原因,网络应该始终是大端的。
- C, c++和c#取决于它们运行的计算机?
- 由于协议的原因,网络应该始终是大端的。如果我们在发送之前不打电话给tonons和htonl怎么样?如果发送者是intel机器上的c++,那么发送的数据将是Little-endian。对吗?
- 所以我们不需要关心端序(调用ntohl和htonl),如果我们知道所有的客户端和服务器将使用具有相同架构的计算机,并将使用相同的程序语言。对吗?
- 至少对于C和c++来说,是的;端序通常取决于机器(但也可能取决于编译器)。对于c#,我不知道。
- 是的,许多网络协议是大端的。如果您不调用
htonl
,那么您将无法在小端机器上创建有效的数据包。 - 所以你应该总是调用
htonl
等(或在你使用的任何语言中等效)。因为即使你今天有一个同质的环境,几乎可以肯定的是,在未来,这种情况会发生变化。
-
计算机间二进制传输的数据依赖于端序。
-
C、c++和c#对端序没有任何要求和要求。
-
网络应遵循协议。这些数字在每个协议输入和输出之后被转换为内部格式。
-
在计算机之间传输二进制数据时,无论是存储在文件中还是立即传输,都只需要担心端序
-
浮点数也有类似的问题
-
许多语言不关心Endianness
严格地说,Java使用与其运行的硬件相同的端序,但是对于JVM用户没有显示,因为您无法在Java中访问原始内存。
- 正确,C语言使用当前运行处理器使用的布局。
- 正确的。
- 无论如何,总是转换为网络字节顺序是一个很好的做法。迟早你会后悔你没有使用按钮(和其他),只是因为它暂时无关紧要。成本通常是最低的,所以除非你有很好的理由不这样做,否则就这样做吧!
用非常抽象的术语来说,只有当您序列化数据时,您必须意识到端序并特定于端序。这有一个非常精确的含义,实际上在某种程度上被c++语言标准所涵盖:
在程序的主体部分,数据来自于某种类型的变量,写为T x;
。到目前为止还很便携;你的程序总是做你想做的,你不需要知道x
是如何在内部表示的。您知道x
的内存从&x
开始,长度为sizeof(T)
字节,但您不知道其他任何信息。如果你真的想知道,你必须将&x
从T*
转换为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
在使用read
和write
这样的操作时,你会发现需要将值转换为字节流,反之亦然,这些操作通常与文件、流或套接字相关。
注意,对于整型值,我们永远不需要知道程序本身的端序——我们只需要知道字节流使用的端序!