不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序,最常见的有两种: 1. Little endian:将低序字节存储在起始地址,就是俗称的小头,地址低位存储值的低位,地址高位存储值的高位 2. Big endian:将高序字节存储在起始地址,就是俗称的大头,地址低位存储值的高位,地址高位存储值的低位 网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。 为进行转换socket提供下面四个函数: ntohl 把unsigned long类型从网络序转换到主机序 使用little endian的系统中 这些函数会把字节序进行转换,使用big endian类型的系统中 这些函数会定义成空宏 在网络程序开发时或跨平台开发时应该注意保证只用一种字节序
主机序根据cpu和操作系统的类型会有Little-Endian(小字节序)、BIG-ENDIAN(大字节序)两种。x86架构的cpu不管操作系统是NT还是unix系的,都是小字节序。而PowerPC 、SPARC和Motorola处理器则很多是大字节序。 在用C/C++写通信程序时,在发送数据前务必用htonl和htons去把整型和短整型的数据进行从主机字节序到网络字节序的转换,而接收数据后对于整型和短整型数据则必须调用ntohl和ntohs实现从网络字节序到主机字节序的转换。如果通信的一方是JAVA程序、一方是C/C++程序时,则需要在 C/C++一侧使用以上几个方法进行字节序的转换,而JAVA一侧,则不需要做任何处理,因为JAVA字节序与网络字节序都是BIG-ENDIAN,只要 C/C++一侧能正确进行转换即可(发送前从主机序到网络序,接收时反变换)。如果通信的双方都是JAVA,则根本不用考虑字节序的问题了。 不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序 1.BIG-ENDIAN、LITTLE-ENDIAN跟多字节类型的数据有关的比如int,short,long型,而对单字节数据byte却没有影响。BIG-ENDIAN就是低位字节排放在内存的高端,高位字节排放在内存的低端。而LITTLE-ENDIAN正好相反。 比如 int a = 0x05060708 在BIG-ENDIAN的情况下存放为: 字节号 0 1 2 3 数据 05 06 07 08 在LITTLE-ENDIAN的情况下存放为: 字节号 0 1 2 3 数据 08 07 06 05 2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有关的,每一种CPU不是BIG-ENDIAN就是LITTLE- ENDIAN、。IA架构的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola处理器。这其实就是所谓的主机字节序。而网络字节序是指数据在网络上传输时是大头还是小头的,在Internet的网络字节序是BIG-ENDIAN。所谓的JAVA字节序指的是在JAVA虚拟机中多字节类型数据的存放顺序,JAVA字节序也是BIG-ENDIAN。 3.所以在用C/C++写通信程序时,在发送数据前务必用htonl和htons去把整型和短整型的数据进行从主机字节序到网络字节序的转换,而接收数据后对于整型和短整型数据则必须调用ntohl和ntohs实现从网络字节序到主机字节序的转换。如果通信的一方是JAVA程序、一方是 C/C++程序时,则需要在C/C++一侧使用以上几个方法进行字节序的转换,而JAVA一侧,则不需要做任何处理,因为JAVA字节序与网络字节序都是 BIG-ENDIAN,只要C/C++一侧能正确进行转换即可(发送前从主机序到网络序,接收时反变换)。如果通信的双方都是JAVA,则根本不用考虑字节序的问题了。 4.如果网络上全部是PowerPC,SPARC和Motorola CPU的主机那么不会出现任何问题,但由于实际存在大量的IA架构的CPU,所以经常出现数据传输错误。 5.文章开头所提出的问题,就是因为程序运行在X86架构的PC SERVER上,发送数据的一端用C实现的,接收一端是用JAVA实现的,而发送端在发送数据前未进行从主机字节序到网络字节序的转换,这样接收端接收到的是LITTLE-ENDIAN的数据,数据解释自然出错。 |