大端模式与小端模式、网络字节顺序与主机字节顺序

合集下载

处理器字节大小端存储方式、网络字节顺序(总结)

处理器字节大小端存储方式、网络字节顺序(总结)

处理器字节大小端存储方式、网络字节顺序(总结)1、大小端存储方式为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。

但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。

因此就导致了大端存储模式和小端存储模式。

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。

对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。

小端模式,刚好相反。

对于32bit的int型,如下:0000430: e684 6c4e 0100 1800 53ef 0100 0100 00000000440: b484 6c4e 004e ed00 0000 0000 0100 0000在大端模式下,前32位应该这样读: e6 84 6c 4e ,在小端模式下,前32位应该这样读: 4e6c 84 e6我们常用的X86结构是小端模式,而KEIL C51则为大端模式。

VC6.0编译程序如下:1. int i = 0x1234;2.3. printf("&i address is %p\n", &i);4. printf("&i+1 address is %p\n", &i+1);5. printf("&i address data is %p\n\n",*(&i));6.7. printf("(char*)&i address is %p\n", (char*)&i);8. printf("(char*)&i+1 address is %p\n", (char*)&i+1);9. printf("(char*)&i address data is %p\n", *(char*)&i);10. printf("(char*)&i+1 address data is %p\n", *((char*)&i+1));结果如下:&i address is 0012FF7C&i+1 address is 0012FF80&i address data is 00001234(char*)&i address is 0012FF7C(char*)&i+1 address is 0012FF7D(char*)&i address data is 00000034(char*)&i+1 address data is 000000122、网络字节顺序我们知道网络上的数据流是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它是将这个字节作为高位还是低位来处理呢?网络字节序定义:收到的第一个字节被当作高位看待,这就要求发送端发送的第一个字节应当是高位。

字节序,大端,小端的概念

字节序,大端,小端的概念

字节序,大端,小端的概念大端、小端:大小端是指CPU存储数据的方式,比如一个0x01020304这个整数,在WIN、Linux下在内存中的布局如下[01][02][03][04] 注意左边是高地址,而右边是低地址在UNIX下则是[04][03][02][01] 注意左边是高地址,而右边是低地址通俗的说,和WIN下的内存布局一致的就是小端,和UNIX下一致的就是大端。

其实在以前还出现过中端的的机型,不过这些机型也太“孤僻”了,已经落伍没人生产没人用了。

网络字节序:其实是指网络传输的字节序,这个字节序可能是大端序或者小端序,这取决于软件开始时通讯双方的协议规定。

平时,如果有人说的网络字节序,那么大家就认为是大端序。

主机字节序:是指主机处理数据时采用的字节序,虽然主机字节序和网络字节序是相对的概念,但是我们说主机字节序的时候,并不默认是之大端或者小端,而是结合机型来确定大小端的。

位序:我们通常所说的字节序是指字节之间的关系,但是即使是一个字节中的某一位(bit)也是有排序的问题的。

位序也有大端序,小端序,中端序,也还有其他的乱七八糟的位序的,但是都不常见。

开发的时候,我们是不用关心位序,编译器和CPU会自己处理这些事情。

算术运算与内存操作运算:算术运算是不改变被运算数据的字节序的,此时我们不用关心所操作的数据到底是什么字节序的。

但是内存操作运算就要注意了,比若我们将一个整数指针强制转换为一个字符指针类型,然后对字符指针类型的四个字节进行算数运算,此时我们必须知道是什么字节序。

不然写出的代码要么是错误的,要么移植到其他机器的时候就不能正常运行。

常见的算术有+ - * / % & | ~ << >> = 等,请注意& | ~ << >> 这几个是算术运算而不是内存操作运算,所以他们进行混合运算的时候不用关心字节序或者位序问题。

赋值运算符仅在数据类型兼容的时候才不涉及字节序问题,才能算作算术运算。

大端模式与小端模式理解

大端模式与小端模式理解

⼤端模式与⼩端模式理解字节序字节序指多字节数据在计算机内存储或者⽹络上传输时各字节的顺序。

(来源:百度百科)为了⽅便,逻辑上将字节序列⾥左边的字节称为⾼字节,右边的字节称为低字节,从左到右,由⾼到低,这样符合数学上的思维习惯,左边是⾼位,右边是地位。

⼤端模式与⼩端模式由于每个字节在内存中都是有地址的,并且内存的地址是顺序排列的,当我们在内存中保存数据时:如果,⾼字节存放在低地址,低字节存放在⾼地址,则为⼤端模式(big-endian)。

如果,低字节存放在低地址,⾼字节存放在⾼地址,则为⼩端模式(little-endian)。

数据从内存保存到⽂件(或发送到⽹络上)时,会受到内存的⼤端模式与⼩端模式的影响。

数据从⽂件读取到(或从⽹络接收到)内存时,需要知道之前是先保存的(或是先发送的)⾼字节还是低字节。

C++⽰例代码1//int 占 4 个字节,short 占 2 个字节int main(){printf("在栈上分配内存\n");int a = 0x11223344;short b = 0x5566;short c = 0x7788;unsigned char *pa = (unsigned char *)&a;unsigned char *pb = (unsigned char *)&b;unsigned char *pc = (unsigned char *)&c;printf("pa 0x%p 0x%x\n", pa, a);printf("pb 0x%p 0x%x\n", pb, b);printf("pc 0x%p 0x%x\n", pc, c);printf("按字节序打印所有字节(⾼字节->低字节)\n");printf("a0 0x%x\n", (a & 0xFF000000) >> (3 * 8));printf("a1 0x%x\n", (a & 0x00FF0000) >> (2 * 8));printf("a2 0x%x\n", (a & 0x0000FF00) >> (1 * 8));printf("a3 0x%x\n", (a & 0x000000FF));printf("b0 0x%x\n", (b & 0xFF00) >> (1 * 8));printf("b1 0x%x\n", (b & 0x00FF));printf("c0 0x%x\n", (c & 0xFF00) >> (1 * 8));printf("c1 0x%x\n", (c & 0x00FF));printf("根据地址顺序打印所有字节(低地址->⾼地址)\n");for (int i = 0; i < 4; i++) {printf("pa[%d] 0x%p 0x%02x\n", i, pa + i, pa[i]);}for (int i = 0; i < 2; i++) {printf("pb[%d] 0x%p 0x%02x\n", i, pb + i, pb[i]);}for (int i = 0; i < 2; i++) {printf("pc[%d] 0x%p 0x%02x\n", i, pc + i, pc[i]);}return 0;}⽰例代码1运⾏结果在栈上分配内存pa 0x007ffe24 0x11223344pb 0x007ffe22 0x5566pc 0x007ffe20 0x7788按字节序打印所有字节(⾼字节->低字节)a0 0x11a1 0x22a2 0x33a3 0x44b0 0x55b1 0x66c0 0x77c1 0x88根据地址顺序打印所有字节(低地址->⾼地址)pa[0] 0x007ffe24 0x44pa[1] 0x007ffe25 0x33pa[2] 0x007ffe26 0x22pb[0] 0x007ffe22 0x66pb[1] 0x007ffe23 0x55pc[0] 0x007ffe20 0x88pc[1] 0x007ffe21 0x77⽰例代码1结果分析a、b、c 在内存中的排列情况:---------------------------------------------------|低地址 -> ⾼地址|---------------------------------------------------|....|0x88|0x77|0x66|0x55|0x44|0x33|0x22|0x11|....|---------------------------------------------------a、b、c 是在栈中分配的,可以看到内存地址是连续的,且 a 的地址相对较⾼,c 的地址相对较低。

大端模式和小端模式

大端模式和小端模式

⼤端模式和⼩端模式⼤端:低地址存⾼位(⾼地址存低位)⼩端:低地址存低位(⾼地址存⾼位)1.故事的起源“endian”这个词出⾃《格列佛游记》。

⼩⼈国的内战就源于吃鸡蛋时是究竟从⼤头(Big-Endian)敲开还是从⼩头(Little-Endian)敲开,由此曾发⽣过六次叛乱,其中⼀个皇帝送了命,另⼀个丢了王位。

我们⼀般将endian翻译成“字节序”,将big endian和little endian称作“⼤尾”和“⼩尾”。

2.什么是Big Endian和Little Endian?在设计计算机系统的时候,有两种处理内存中数据的⽅法。

⼀种叫为little-endian,存放在内存中最低位的数值是来⾃数据的最右边部分(也就是数据的最低位部分)。

⽐如某些⽂件需要在不同平台处理,或者通过Socket通信。

这⽅⾯我们可以借助ntohl(), ntohs(), htonl(), and htons()函数进⾏格式转换,个⼈补充:⼀个操作数作htonl或ntohl结果不⼀定相同,当机器字节序跟⽹络字节序刚好是仅仅big endian和little endian的区别时是相同的。

3. 如何理解Big Endian和Little Endian举个例⼦:int a = 1;a这个数本⾝的16进制表⽰是0x00 00 00 01在内存中怎么存储呢?如果你的CPU是intel x86架构的(基本上就是通常我们说的奔腾cpu),那么就是0x01 0x00 0x00 0x00 , 这也就是所谓的little-endian, 低字节存放在内存的低位.如果你的CPU是⽼式AMD系列的(很⽼很⽼的那种,因为最新的AMD系列已经是x86架构了), 它的字节序就是big-endian, 其内存存储就是0x00 0x00 0x00 0x01在内存中从⾼字节开始存放。

现在世界上绝⼤多数的CPU都是little-endian。

4. 了解big-endian和little-endian有什么作⽤?⼀个重要的作⽤就是了解在⽹络上不同的机器间的数据如何传输。

【转】go语言中int和byte转换方式

【转】go语言中int和byte转换方式

【转】go语⾔中int和byte转换⽅式-------------------------------主机字节序主机字节序模式有两种,⼤端数据模式和⼩端数据模式,在⽹络编程中应注意这两者的区别,以保证数据处理的正确性;例如⽹络的数据是以⼤端数据模式进⾏交互,⽽我们的主机⼤多数以⼩端模式处理,如果不转换,数据会混乱参考;⼀般来说,两个主机在⽹络通信需要经过如下转换过程:主机字节序 —> ⽹络字节序 -> 主机字节序⼤端⼩端区别⼤端模式:Big-Endian就是⾼位字节排放在内存的低地址端,低位字节排放在内存的⾼地址端低地址 --------------------> ⾼地址⾼位字节地位字节⼩端模式:Little-Endian就是低位字节排放在内存的低地址端,⾼位字节排放在内存的⾼地址端低地址 --------------------> ⾼地址低位字节⾼位字节什么是⾼位字节和低位字节例如在32位系统中,357转换成⼆级制为:00000000 00000000 00000001 01100101,其中00000001 | 01100101⾼位字节低位字节int和byte转换在go语⾔中,byte其实是uint8的别名,byte 和 uint8 之间可以直接进⾏互转。

⽬前来只能将0~255范围的int转成byte。

因为超出这个范围,go在转换的时候,就会把多出来数据扔掉;如果需要将int32转成byte类型,我们只需要⼀个长度为4的[]byte数组就可以了⼤端模式下123 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27func f2() {var v2 uint32var b2 [4]bytev2 = 257// 将 257转成⼆进制就是// | 00000000 | 00000000 | 00000001 | 00000001 |// | b2[0] | b2[1] | b2[2] | b2[3] | // 这⾥表⽰b2数组每个下标⾥⾯存放的值 // 这⾥直接使⽤将uint32强转成uint8// | 00000000 0000000 00000001 | 00000001 直接转成uint8后等于 1// |---这部分go在强转的时候扔掉---|b2[3] = uint8(v2)// | 00000000 | 00000000 | 00000001 | 00000001 | 右移8位转成uint8后等于 1// 下⾯是右移后的数据// | | 00000000 | 00000000 | 00000001 |b2[2] = uint8(v2 >> 8)// | 00000000 | 00000000 | 00000001 | 00000001 | 右移16位转成uint8后等于 0 // 下⾯是右移后的数据// | | | 00000000 | 00000000 |b2[1] = uint8(v2 >> 16)// | 00000000 | 00000000 | 00000001 | 00000001 | 右移24位转成uint8后等于 0 // 下⾯是右移后的数据// | | | | 00000000 |b2[0] = uint8(v2 >> 24)fmt.Printf("%+v\n", b2)// 所以最终将uint32转成[]byte数组输出为// [0 0 1 1]} ⼩端模式下123 4 5// 在上⾯我们讲过,⼩端刚好和⼤端相反的,所以在转成⼩端模式的时候,只要将[]byte数组的下标⾸尾对换⼀下位置就可以了func f3() {var v3 uint326 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 var b3 [4]bytev3 = 257// 将 256转成⼆进制就是// | 00000000 | 00000000 | 00000001 | 00000001 |// | b3[0] | b3[1] | b3[2] | [3] | // 这⾥表⽰b3数组每个下标⾥⾯存放的值// 这⾥直接使⽤将uint32l强转成uint8// | 00000000 0000000 00000001 | 00000001 直接转成uint8后等于 1// |---这部分go在强转的时候扔掉---|b3[0] = uint8(v3)// | 00000000 | 00000000 | 00000001 | 00000001 | 右移8位转成uint8后等于 1 // 下⾯是右移后的数据// | | 00000000 | 00000000 | 00000001 |b3[1] = uint8(v3 >> 8)// | 00000000 | 00000000 | 00000001 | 00000001 | 右移16位转成uint8后等于 0 // 下⾯是右移后的数据// | | | 00000000 | 00000000 |b3[2] = uint8(v3 >> 16)// | 00000000 | 00000000 | 00000001 | 00000001 | 右移24位转成uint8后等于 0 // 下⾯是右移后的数据// | | | | 00000000 |b3[3] = uint8(v3 >> 24)fmt.Printf("%+v\n", b3)// 所以最终将uint32转成[]byte数组输出为// [1 1 0 0 ]} go转换demo1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16//整形转换成字节func IntToBytes(n int) []byte {x := int32(n)bytesBuffer := bytes.NewBuffer([]byte{})binary.Write(bytesBuffer, binary.BigEndian, x) return bytesBuffer.Bytes()}//字节转换成整形func BytesToInt(b []byte) int {bytesBuffer := bytes.NewBuffer(b)var x int32binary.Read(bytesBuffer, binary.BigEndian, &x) return int(x)}。

网络字节顺序、大端法、小端法

网络字节顺序、大端法、小端法

网络字节顺序、大端法、小端法分类:j2se 2006-03-23 23:53 3213人阅读评论(1) 收藏举报在国内的4种短信协议的协议头部分,都定义了4个字节长度的message length字段,字段的数据类型为无符号整形(也就是说,这个字段的范围是0-2^16-1);而在java语言中,没有无符号整形这种数据类型(如果用int类型来表示,由于java中int型是有符号数,则会发送溢出),我设想将message length存入long类型中,将数字的大小控制在0-2^16-1范围之内,当超过此范围归零重新开始。

在网络传输时,将long类型先转化为byte数组,步骤如下:long l;byte[] b;b[0]=(byte)(l>>>24);b[1]]=(byte)(l>>>16);b[2]]=(byte)(l>>>8);b[3]]=(byte)(l);此时,b[]中就按照网络字节顺序(大端法,即l的高位数据存放在byte[]的低位地址,因为地址是从低向高发展的)存放着4个bytes的数据使用OutputStream的public void write(byte[] b,int off,int len)方法来向Socket写字节流,写byte[0]至byte[3]的字节。

java.ioClass OutputStreamwritepublic abstract void write(int b) throws IOExceptionWrites the specified byte to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.Subclasses of OutputStream must provide animplementation for this method.Parameters:b - the byte.Throws:IOException- if an I/O error occurs. In particular, an IOException may be thrown if the output stream has been closed.writepublic void write(byte[] b, int off, int len) throws IOException Writes len bytes from the specified byte array starting at offset off to this output stream. The general contract for write(b, off, len) is that some of the bytes in the array b are written to the output stream in order;element b[off] is the first byte written and b[off+len-1] is the last byte written by this operation.The write method of OutputStream calls the writemethod of one argument on each of the bytes to be written out. Subclasses are encouraged tooverride this method and provide a moreefficient implementation.If b is null, a NullPointerException is thrown.If off is negative, or len is negative, or off+len isgreater than the length of the array b, then anIndexOutOfBoundsException is thrown.Parameters:b - the data.off - the start offset in the data.len - the number of bytes to write.Throws:IOException- if an I/O error occurs. In particular, an IOException is thrown if the output stream is closed.------关于网络、主机字节顺序的文章/developerworks/cn/java/l-d atanet/index.html主机和网络字节序的转换最近使用C#进行网络开发,需要处理ISO8583报文,由于其中有些域是数值型的,于是在传输的时候涉及到了字节序的转换。

小端字节序与大端字节序

小端字节序与大端字节序

⼩端字节序与⼤端字节序
端模式分为:⼩端字节序和⼤端字节序,也就是字节在内存中的顺序。

⼩端字节序:低字节存于内存低地址;⾼字节存于内存⾼地址。

如⼀个long型数据0x12345678
0x0029f458 0x78
0x0029f459 0x56
0x0029f45a 0x34
0x0029f45b 0x12
在以上数据存放于内存中的表现形式中,0x0029f458 < 0x0029f459 < 0x0029f45a < 0x0029f45b,可以知道内存的地址是由低到⾼的顺序;⽽数据的字节也是由低到⾼的,故以上字节序是⼩端字节序。

⼤端字节序:⾼字节存于内存低地址;低字节存于内存⾼地址。

0x0029f458 0x12
0x0029f459 0x34
0x0029f45a 0x56
0x0029f45b 0x79
在以上数据存放于内存中的表现形式中,0x0029f458 < 0x0029f459 < 0x0029f45a < 0x0029f45b,可以知道内存的地址是由低到⾼的顺序;⽽数据的字节却是由⾼到低的,故以上字节序是⼤端字节序。

⽹络字节序:就是⼤端字节序。

规定不同系统间通信⼀律采⽤⽹络字节序。

在VC中的实验如下:
int temp = 0x12345678;
调试中,该变量在内存中的字节数据是78 56 34 12,内存中的存放地址是:0x0029f458,0x0029f459,0x0029f45a,0x0029f45b;刚好符合低位存于低地址中,说明VC遵循⼩端字节序。

大端(BigEndian)与小端(LittleEndian)详解

大端(BigEndian)与小端(LittleEndian)详解

大端(BigEndian)与小端(LittleEndian)详解大端(Big Endian)与小端(Little Endian)简介///////////////////////////////////////////////////////1. 你从哪里来?端模式(Endian)的这个词出自Jonathan Swift书写的《格列佛游记》。

这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big Endian,从尖头开始将鸡蛋敲开的人被归为Littile Endian。

小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。

在计算机业Big Endian和Little Endian也几乎引起一场战争。

在计算机业界,Endian表示数据在存储器中的存放顺序。

采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。

下文举例说明在计算机中大小端模式的区别。

//////////////////////////////////////////////////////2. 读书百遍其义自见小端口诀: 高高低低 -> 高字节在高地址, 低字节在低地址大端口诀: 高低低高 -> 高字节在低地址, 低字节在高地址long test = 0x313233334;小端机器:低地址 --> 高地址00000010: 34 33 32 31 -> 4321大端机器:低地址 --> 高地址00000010: 31 32 33 34 -> 4321test变量存储的是的0x10这个地址,那编译器怎么知道是读四个字节呢? -> 根据变量test的类型long 可知这个变量占据4个字节.那编译器怎么读出这个变量test所代表的值呢? -> 这就根据是little endian还是big endian来读取所以, 小端, 其值为0x31323334; 大端, 其值为0x34333231htonl(test) 的情况: ->其值为: 0x34333231小端机器:00000010: 31 32 33 34 -> 1234大端机器:00000010: 34 33 32 31 -> 4321/////////////////////////////////////////////////////////////////// //////////////////3. 拿来主义Byte Endian是指字节在内存中的组织,所以也称它为Byte Ordering,或Byte Order。

从大端字节顺序转换为主机字节顺序的方法

从大端字节顺序转换为主机字节顺序的方法

文章标题:深入探讨大端字节顺序转换为主机字节顺序的方法在计算机科学中,大端字节顺序和小端字节顺序是描述多字节数据在内存中存储方式的概念。

在大端字节顺序中,数据的高位字节存储在低位置区域,而小端字节顺序则相反。

当我们需要在不同字节顺序的机器之间传输数据时,我们就需要进行字节顺序转换。

本文将深入探讨如何将数据从大端字节顺序转换为主机字节顺序,帮助读者更深入地理解这一主题。

1. 了解大端字节顺序和小端字节顺序让我们简单了解一下大端字节顺序和小端字节顺序。

在大端字节顺序中,数据的高位字节存储在低位置区域,而小端字节顺序则相反,数据的高位字节存储在高位置区域。

这两种字节顺序的存在导致了在不同字节顺序的机器之间进行数据传输时可能出现的问题,因此需要进行字节顺序转换。

2. 为什么需要进行字节顺序转换在现实应用中,我们可能会遇到不同字节顺序的机器之间需要进行数据交换的情况,比如网络传输、文件格式转换等。

在这些情况下,如果我们不进行字节顺序转换,就有可能导致接收方解析数据时出现错误。

了解如何进行字节顺序转换是非常重要的。

3. 方法一:逐字节交换最简单的方法是逐字节地交换数据中的字节顺序。

如果有一个32位的整数数据,在大端字节顺序中,可以先将其拆分成4个8位的字节,然后将这4个字节依次按小端顺序重新组合成一个新的32位整数数据。

这种方法的优势是简单直观,但是需要逐字节操作,效率较低。

4. 方法二:使用位运算另一种方法是使用位运算来进行字节顺序转换。

以将大端字节顺序转换为小端字节顺序为例,我们可以使用位运算来直接进行字节顺序的交换。

这种方法相对于逐字节交换来说,效率更高,代码更简洁。

5. 方法三:使用标准库函数在实际开发中,我们还可以使用一些标准库函数来进行字节顺序转换,比如C语言中的`htonl`和`ntohl`函数。

这些函数可以直接将数据从大端字节顺序转换为主机字节顺序或者相反方向。

使用标准库函数能够更加方便地进行字节顺序转换,并且能够提高代码的可移植性。

大端和小端(BigendianandLittleendian)

大端和小端(BigendianandLittleendian)

⼤端和⼩端(BigendianandLittleendian)⼀、⼤端和⼩端的问题对于整型、长整型等数据类型,Big endian 认为第⼀个字节是最⾼位字节(按照从低地址到⾼地址的顺序存放数据的⾼位字节到低位字节);⽽ Little endian 则相反,它认为第⼀个字节是最低位字节(按照从低地址到⾼地址的顺序存放据的低位字节到⾼位字节)。

例如,假设从内存地址 0x0000 开始有以下数据:0x0000 0x0001 0x0002 0x00030x12 0x34 0xab 0xcd如果我们去读取⼀个地址为 0x0000 的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序为little-endian,则读出结果为0xcdab3412。

如果我们将0x1234abcd 写⼊到以 0x0000 开始的内存中,则Little endian 和 Big endian 模式的存放结果如下:地址 0x0000 0x0001 0x0002 0x0003big-endian 0x12 0x34 0xab 0xcdlittle-endian 0xcd 0xab 0x34 0x12⼀般来说,x86 系列 CPU 都是 little-endian 的字节序,PowerPC 通常是 big-endian,⽹络字节顺序也是 big-endian还有的CPU 能通过跳线来设置 CPU ⼯作于 Little endian 还是 Big endian 模式。

对于0x12345678的存储:⼩端模式:(从低字节到⾼字节)地位地址 0x78 0x56 0x34 0x12 ⾼位地址⼤端模式:(从⾼字节到低字节)地位地址 0x12 0x34 0x56 0x78 ⾼位地址⼆、⼤端⼩端转换⽅法htonl() htons() 从主机字节顺序转换成⽹络字节顺序ntohl() ntohs() 从⽹络字节顺序转换为主机字节顺序Big-Endian转换成Little-Endian#define BigtoLittle16(A) ((((uint16)(A) & 0xff00) >> 8) | (((uint16)(A) & 0x00ff) << 8))#define BigtoLittle32(A) ((((uint32)(A) & 0xff000000) >> 24) | (((uint32)(A) & 0x00ff0000) >> 8) | \(((uint32)(A) & 0x0000ff00) << 8) | (((uint32)(A) & 0x000000ff) << 24))三、⼤端⼩端检测⽅法如何检查处理器是big-endian还是little-endian?C程序:int i = 1;char *p = (char *)&i;if(*p == 1)printf("Little Endian");elseprintf("Big Endian");⼤⼩端存储问题,如果⼩端⽅式中(i占⾄少两个字节的长度)则i所分配的内存最⼩地址那个字节中就存着1,其他字节是0.⼤端的话则1在i的最⾼地址字节处存放,char是⼀个字节,所以强制将char型量p指向i则p指向的⼀定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是⼩端。

详解大端模式和小端模式

详解大端模式和小端模式

一、大端模式和小端模式的起源关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。

战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。

然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。

据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。

这个其实讽刺当时英国和法国之间持续的冲突。

Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。

二、什么是大端和小端Big-Endian和Little-Endian的定义如下:1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:1)大端模式:低地址-----------------> 高地址0x12 | 0x34 | 0x56 | 0x782)小端模式:低地址------------------> 高地址0x78 | 0x56 | 0x34 | 0x12可见,大端模式和字符串的存储模式类似。

3)下面是两个具体例子:16bit宽的数0x1234在Little-endian模式(以及Big-endian 模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:32bit宽的数0x12345678在Little-endian模式以及Big-endian 模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:4)大端小端没有谁优谁劣,各自优势便是对方劣势:小端模式:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。

举例说明多字节数据存储的小端方式和大端方式

举例说明多字节数据存储的小端方式和大端方式

在计算机科学中,多字节数据存储的小端方式和大端方式是非常重要的概念。

它们指的是在存储和读取多字节数据时,字节的排列顺序。

具体来说,小端方式是指将最低有效字节存储在最低内存位置区域处,而大端方式则是将最高有效字节存储在最低内存位置区域处。

这种存储方式在网络通信、文件存储和数据传输中起着至关重要的作用。

接下来,我将通过举例来说明多字节数据存储的小端方式和大端方式。

我们来看一个简单的例子,假设我们要存储一个16位的整数16706,用二进制表示为0100000100000010。

在小端方式下,存储顺序为01000010 00000010,而在大端方式下,存储顺序为00000010 01000010。

进一步来看,如果我们需要存储一个32位的整数,在小端方式下,存储顺序为01000010 00000010 10101010 11111111,而在大端方式下,存储顺序为11111111 10101010 00000010 01000010。

这种存储方式的不同会在不同的架构和系统中产生影响。

在网络通信中,如果一台机器采用小端方式存储数据,而另一台机器采用大端方式,就会导致通信错误,因为它们会误解对方发送的数据。

另一个例子是在文件存储中,如果一个文件是以小端方式存储的,而在读取它的时候却以大端方式解析,就会导致数据的错误解析和处理。

小端方式和大端方式在不同的场景中都有它们各自的作用和影响。

在实际应用中,我们需要根据具体的情况来选择适合的存储方式,以确保数据的正确传输和读取。

对于我个人而言,我更倾向于小端方式存储多字节数据,因为它更符合我的直觉和习惯。

在实际工作中,我也会根据具体情况来选择合适的存储方式,以确保数据的正确性和高效性。

多字节数据存储的小端方式和大端方式是计算机科学中一个重要而复杂的概念。

通过举例说明,我们能更好地理解它们的不同以及应用场景。

在实际工作中,合理选择存储方式是非常重要的,它涉及到数据的正确性和系统的高效性。

大端小端

大端小端

一、概念及详解在各种体系的计算机中通常采用的字节存储机制主要有两种:big-endian和little-endian,即大端模式和小端模式。

先回顾两个关键词,MSB和LSB:MSB:MoST Significant Bit ------- 最高有效位LSB:Least Significant Bit ------- 最低有效位大端模式(big-edian)big-endian:MSB存放在最低端的地址上。

举例,双字节数0x1234以big-endian的方式存在起始地址0x00002000中:| data |<-- address| 0x12 |<-- 0x00002000| 0x34 |<-- 0x00002001在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为例):bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15------MSB----------------------------------LSBval | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |+--------------------------------------------+= 0x8 B 8 A小端模式(little-endian)little-endian:LSB存放在最低端的地址上。

举例,双字节数0x1234以little-endian的方式存在起始地址0x00002000中:| data |<-- address| 0x34 |<-- 0x00002000| 0x12 |<-- 0x00002001在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如下(以双字节数0x8B8A为例):bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0------MSB-----------------------------------LSBval | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |+---------------------------------------------+= 0x8 B 8 A二、数组在大端小端情况下的存储:以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:Big-Endian: 低地址存放高位,如下:高地址---------------buf[3] (0x78) -- 低位buf[2] (0x56)buf[1] (0x34)buf[0] (0x12) -- 高位---------------低地址Little-Endian: 低地址存放低位,如下:高地址---------------buf[3] (0x12) -- 高位buf[2] (0x34)buf[1] (0x56)buf[0] (0x78) -- 低位--------------低地址三、大端小端转换方法:Big-Endian转换成Little-Endian如下:#define BigtoLittle16(A) ((((uint16)(A) & 0xff00) >> 8) | \(((uint16)(A) & 0x00ff) << 8))#define BigtoLittle32(A) ((((uint32)(A) & 0xff000000) >> 24) | \(((uint32)(A) & 0x00ff0000) >> 8) | \(((uint32)(A) & 0x0000ff00) << 8) | \(((uint32)(A) & 0x000000ff) << 24))四、大端小端检测方法:如何检查处理器是big-endian还是little-endian?联合体uniON的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。

大端、小端与网络字节序

大端、小端与网络字节序

⼤端、⼩端与⽹络字节序⼤端(Big-Endian),⼩端(Little-Endian)以及⽹络字节序的概念在编程中经常会遇到,⽹络字节序(Network Byte Order)⼀般是指⼤端(Big-Endian,对⼤部分⽹络传输协议⽽⾔)传输,⼤端⼩端的概念是⾯向多字节数据类型的存储⽅式定义的,⼩端就是低位在前(低位字节存在内存低地址,字节⾼低顺序和内存⾼低地址顺序相同),⼤端就是⾼位在前,(其中“前”是指靠近内存低地址,存储在硬盘上就是先写那个字节)。

概念上字节序也叫主机序。

⼀、⼤⼩端概念1、⾸先⼤⼩端是⾯向多字节类型定义的,⽐如2字节、4字节、8字节整型、长整型、浮点型等,单字节的字符串⼀般不⽤考虑。

2、⼤端⼩端存储、传输、以及接收处理需要对应。

3、⼤端(Big-Endian)就是⾼字节(MSB)在前,内存存储体现上,数据的⾼位更加靠近低地址。

(低地址存⾼字节)4、⼩端(Little-Endian)就是低字节(LSB)在前,内存存储体现上,数据的低位更加靠近低地址。

(低地址存低字节)5、⽹络字节序⼀般是指⼤端传输。

⼆、⼤⼩端存储⽰例假设⼀个32位 unsigned int型数据0x12 34 56 78,⼤⼩端8位存储⽅式如下:⼤端存储⽅式为0x12 34 56 78⼩端存储⽅式为0x78 56 34 12,如下图。

三、常见CPU的⼤⼩端存储⽅式不同CPU有不同的字节序类型,典型的使⽤⼩端存储的CPU有:Intel x86和ARM典型的使⽤⼤端存储CPU有:Power PC、MIPS UNIX和HP-PA UNIX注:以上CPU需根据具体型号查询⼿册,有的CPU甚⾄可能同时能⽀持两种存储⽅式。

上⽂说的⽹络字节顺序则是表⽰⽹络传输时的字节序,按照TCP/IP协议是按照⼤端传输⽅式,也就是⾼字节先⾛(先传12,接着34,56,78),这跟本机存储和服务器存储没有关系,只要确保双⽅解析对应即可。

四、四个转换函数C/C++中有如下四个常⽤的转换函数,这四个函数在⼩端系统中⽣效,⼤端系统由于和⽹络字节序相同,所以⽆需转换。

大小端定义——精选推荐

大小端定义——精选推荐

⼤⼩端定义
⼤⼩端的定义
Big-Endian和Little-Endian的定义如下:
Little-Endian就是低位字节排放在内存的低地址端,⾼位字节排放在内存的⾼地址端。

Big-Endian就是⾼位字节排放在内存的低地址端,低位字节排放在内存的⾼地址端。

举⼀个例⼦,⽐如数字0x12 34 56 78在内存中的表⽰形式为:
⼤端模式:
低地址 -----------------> ⾼地址
0x12 | 0x34 | 0x56 | 0x78
⾼位--------------------低位
内存中的表⽰:
buf[0]=0x12
buf[1]=0x34
buf[2]=0x56
buf[3]=0x78
可见,⼤端模式和字符串的存储模式类似。

⼩端模式:
低地址 ------------------> ⾼地址
0x78 | 0x56 | 0x34 | 0x12
低位---------------------⾼位
内存中的表⽰
buf[0]=0x78
buf[1]=0x56
buf[2]=0x34
buf[3]=0x12
⽹络中的字节序
⽹络中的数据均使⽤⼤端模式,发送端需要使⽤htons/htonl来确保转换为⼤端模式(⽹络字节序),接收端需要使⽤ntohs/ntohl来确保转换为本机的⼤(⼩)端模式(主机字节序)。

应⽤层的字节序
要根据具体应⽤协议去区分,⽐如Mysql通信协议,使⽤的是the least significant byte first,其实就是⼩端⽅式。

大端存储模式和小端存储模式

大端存储模式和小端存储模式

⼤端存储模式和⼩端存储模式CPU存储数据操作的最⼩单位是⼀个字节。

⼤端存储模式(Big-Endian),⼩端存储模式(Little-Endian)是常见的⼆种字节序。

Little-Endian:低位字节排放在内存的低地址端,⾼位字节排放在内存的⾼地址端。

Big-Endian:⾼位字节排放在内存的低地址端,低位字节排放在内存的⾼地址端。

⽐如0x12345678在内存中的表⽰形式为:采⽤⼤端模式:低地址 --------------------> ⾼地址0x12 | 0x34 | 0x56 | 0x78采⽤⼩端模式:低地址 --------------------> ⾼地址0x78 | 0x56 | 0x34 | 0x12也就是说Big-Endian是指低地址存放最⾼有效字节(MSB),⽽Little-Endian则是低地址存放最低有效字节(LSB)。

⼀般操作系统采⽤的都是⼩端模式,⽽通讯协议采⽤⼤端模式。

1)常见的CPU的字节序Big-Endian : PowerPC,IBM,SunLittle-Endian:x86ARM既可以⼯作在⼤端模式,也可以⼯作在⼩端模式。

2)常见的⽂件的字节序Adobe PS : Big-EndianBMP :Little-EndianGIF : Little-EndianJPEG:Big-Endian此外Java和所有的⽹络通信协议都是使⽤⼤端模式的编码事实上存在字节序,也存在⽐特序。

CPU存储⼀个字节的数据时其字节内的8个⽐特之间的顺序也有Big-Endian和Little-Endian之分。

⽐如字节0xA0的存储格式如下:Big-EndianMSB LSB-------------------------------->1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |Little-EndianLSB MSB-------------------------------->0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |实际上,由于CPU存储数据操作的最⼩单位是⼀个字节,其内部的⽐特序是什么样对我们的程序来说是⼀个⿊盒⼦,也就是说,你给我⼀个指向0xA0这个数的指针,对于Big-Endian⽅式的CPU来说,它是从左往右依次读取这个数的8个⽐特;⽽对于Little-Endian⽅式的CPU来说,则正好相反,是从右往左依次读取这个数的8个⽐特。

关于网络字节序和主机字节序的解析

关于网络字节序和主机字节序的解析

关于网络字节序不同的CPU 有不同的字节序类型这些字节序是指整数在内存中保存的顺序这个叫做主机序最常见的有两种1 .Little endian :将低序字节存储在起始地址2 .Big endian :将高序字节存储在起始地址LE little-endian最符合人的思维的字节序地址低位存储值的低位地址高位存储值的高位怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说低位值小,就应该放在内存地址小的地方,也即内存地址低位反之,高位值就应该放在内存地址大的地方,也即内存地址高位BE big-endian最直观的字节序地址低位存储值的高位地址高位存储值的低位为什么说直观,不要考虑对应关系只需要把内存地址从左到右按照由低到高的顺序写出把值按照通常的高位到低位的顺序写出两者对照,一个字节一个字节的填充进去例子:在内存中双字0x01020304(DWORD) 的存储方式内存地址4000 4001 4002 4003LE 04 03 02 01BE 01 02 03 04例子:如果我们将0x1234abcd 写入到以0x0000 开始的内存中,则结果为big-endian little-endian0x0000 0x12 0xcd0x0001 0x23 0xab0x0002 0xab 0x340x0003 0xcd 0x12x86 系列CPU 都是little-endian 的字节序.网络字节顺序是TCP/IP 中规定好的一种数据表示格式,它与具体的CPU 类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。

网络字节顺序采用big endian 排序方式。

为了进行转换bsd socket 提供了转换的函数有下面四个htons 把unsigned short 类型从主机序转换到网络序htonl 把unsigned long 类型从主机序转换到网络序ntohs 把unsigned short 类型从网络序转换到主机序ntohl 把unsigned long 类型从网络序转换到主机序在使用little endian 的系统中这些函数会把字节序进行转换在使用big endian 类型的系统中这些函数会定义成空宏同样在网络程序开发时或是跨平台开发时也应该注意保证只用一种字节序不然两方的解释不一样就会产生bug.注:1 、网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l 是long h 是host n 是network)2 、不同的CPU 上运行不同的操作系统,字节序也是不同的,参见下表。

大端模式与小端模式、网络字节顺序与主机字节顺序

大端模式与小端模式、网络字节顺序与主机字节顺序

大端模式与小端模式、网络字节顺序与主机字节顺序1. 大端模式与小端模式1.1 概念及详解在各种体系的计算机中通常采用的字节存储机制主要有两种:big-endian和little-endian,即大端模式和小端模式。

先回顾两个关键词,MSB和LSB:MSB: Most Significant Bit ------- 最高有效位LSB:Least Significant Bit ------- 最低有效位1.1.1 大端模式(big-edian):MSB存放在最低端的地址上。

举例,假设双字节数0x1234以big-endian的方式存在起始地址0x00002000中:| data |<-- address| 0x12 |<-- 0x00002000| 0x34 |<-- 0x00002001在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为例):bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 |-----MSB-----------------------------------LSBval | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |+-----------------------------------------+= 0x8 B 8 A1.1.2 小端模式(little-endian):LSB存放在最低端的地址上。

举例,双字节数0x1234以little-endian的方式存在起始地址0x00002000中:| data |<-- address| 0x34 |<-- 0x00002000| 0x12 |<-- 0x00002001在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如下(仍以双字节数0x8B8A为例):bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0 |-----MSB-----------------------------------LSBval | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |+-----------------------------------------+= 0x8 B 8 A1.2 数组在大端小端情况下的存储以unsigned int value = 0x12345678 为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:Big-Endian: 低地址存放高位,如下:高地址---------------buf[3] (0x78) -- 低位buf[2] (0x56)buf[1] (0x34)buf[0] (0x12) -- 高位---------------低地址Little-Endian: 低地址存放低位,如下:高地址---------------buf[3] (0x12) -- 高位buf[2] (0x34)buf[1] (0x56)buf[0] (0x78) -- 低位--------------低地址1.3 大端小端转换方法Big-Endian转换成Little-Endian如下:#define BigtoLittle16(A) ((((uint16)(A) & 0xff00) >> 8) | \(((uint16)(A) & 0x00ff) << 8))#define BigtoLittle32(A) ((((uint32)(A) & 0xff000000) >> 24) | \ (((uint32)(A) & 0x00ff0000) >> 8) | \(((uint32)(A) & 0x0000ff00) << 8) | \(((uint32)(A) & 0x000000ff) << 24))1.4 大端小端检测方法如何检查处理器是big-endian还是little-endian?联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写:int checkCPUendian(){union{unsigned int a;unsigned char b;} un;c.a = 1;return (c.b == 1);}2. 网络字节顺序2.1 概述> 字节内的比特位不受这种顺序的影响比如一个字节 1000 0000 (或表示为十六进制80H)不管是什么顺序其内存中的表示法都是这样。

关于网络字节序和主机字节序

关于网络字节序和主机字节序

关于⽹络字节序和主机字节序我们在进⾏⽹络编程的时候,有时候会遇到字节序转换的问题,为什么呢?因为我们都知道计算机对于数据的存储有两种⽅式,⼀种是⼤端模式,⼀种是⼩端模式,但是我们数据在⽹络上传输都是⼤端模式,这是为了统⼀。

当我们发送端主机是⼩端模式时,我们要将主机的⼩端模式的字节序转换成⽹络的⼤端模式当我们接收端主机是⼩端模式时,我们要将⽹络的⼤端模式转换为接收端主机的⼩端模式当我们发送端主机是⼤端模式时,我们⽆需进⾏转换当我们接收端主机是⼤端模式时,我们也⽆需进⾏转换htonl() 将主机字节序转换为⽹络字节序 longntohl() 将⽹络字节序转换为主机字节序 longhtons() 将主机字节序转换为⽹络字节序 shortntohs() 将⽹络字节序转换为主机字节序 short在使⽤little endian的系统中这些函数会把字节序进⾏转换在使⽤big endian类型的系统中这些函数会定义成空宏所以不要管主机到底是什么字节序,你只要转换即可,即使⽤htonl()。

这些函数,如果你的机⼦是⼤端模式的话,那么这些函数反正就是空的宏定义,所以这样⼦的话,你⽆须关⼼,你⾃⼰的机⼦到底是⼤端的还是⼩端的。

详解请看下⾯:不同的CPU有不同的字节序类型这些字节序是指整数在内存中保存的顺序这个叫做主机序最常见的有两种:1. Little endian:将低序字节存储在起始地址2. Big endian:将⾼序字节存储在起始地址LE little-endian最符合⼈的思维的字节序地址低位存储值的低位地址⾼位存储值的⾼位怎么讲是最符合⼈的思维的字节序,是因为从⼈的第⼀观感来说低位值⼩,就应该放在内存地址⼩的地⽅,也即内存地址低位反之,⾼位值就应该放在内存地址⼤的地⽅,也即内存地址⾼位BE big-endian最直观的字节序地址低位存储值的⾼位地址⾼位存储值的低位为什么说直观,不要考虑对应关系只需要把内存地址从左到右按照由低到⾼的顺序写出把值按照通常的⾼位到低位的顺序写出两者对照,⼀个字节⼀个字节的填充进去例⼦:在内存中双字0x01020304(DWORD)的存储⽅式内存地址4000 4001 4002 4003LE 04 03 02 01BE 01 02 03 04例⼦:如果我们将0x1234abcd写⼊到以0x0000开始的内存中,则结果为big-endian little-endian0x0000 0x12 0xcd0x0001 0x34 0xab0x0002 0xab 0x340x0003 0xcd 0x12x86系列CPU都是little-endian的字节序.⽹络字节顺序是TCP/IP中规定好的⼀种数据表⽰格式,它与具体的CPU类型、操作系统等⽆关,从⽽可以保证数据在不同主机之间传输时能够被正确解释。

网络字节序 主机字节序

网络字节序 主机字节序

网络字节序主机字节序
计算机在进行数据传输时,需要在不同的设备之间进行
信息交换。

由于每个设备可能具有不同的硬件结构和字节序,因此需要一种标准化的网络字节序来确保数据在不同的设备之间能够正确交换。

网络字节序指的是在网络上通用的规定的字节序,通常
采用大端字节序。

而主机字节序指的是主机处理器所采用的字节序。

在大多数现代处理器中,主机字节序也采用大端字节序。

当数据从主机端传输到网络上时,需要将数据转换为网
络字节序。

当数据从网络中回传主机端时,也需要将数据转换为主机字节序。

这种转换通常由操作系统的网络库自动完成,但是在某些情况下需要手动进行字节序转换。

网络字节序的重要性在于,它可以确保不同设备之间的
数据传输能够正确进行。

如果不同设备使用不同的字节序,数据就会出现错位,导致数据传输无法完成,或者数据内容出现混乱。

因此,在进行跨设备的数据传输时,通常需要将数据转换为网络字节序,以确保数据包的正确传输。

除了字节序之外,网络传输还会受到许多其他因素的影响。

例如,传输的数据包大小、数据压缩、传输协议的选择等都会影响数据传输的速度和效率。

在建立网络连接时,需要考虑这些因素,并进行适当的配置和调整,以确保数据传输的高效和安全。

总的来说,网络字节序和主机字节序是计算机网络中非
常重要的概念。

理解这两个概念对于计算机专业人员和网络管
理员来说都非常重要,因为它们涉及到计算机网络中的许多关键问题。

在实际的网络应用中,正确使用和配置字节序转换机制可以确保数据的正确传输,从而提高网络的效率和安全性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

大端模式与小端模式、网络字节顺序与主机字节顺序1. 大端模式与小端模式1.1 概念及详解在各种体系的计算机中通常采用的字节存储机制主要有两种:big-endian和little-endian,即大端模式和小端模式。

先回顾两个关键词,MSB和LSB:MSB: Most Significant Bit ------- 最高有效位LSB:Least Significant Bit ------- 最低有效位1.1.1 大端模式(big-edian):MSB存放在最低端的地址上。

举例,假设双字节数0x1234以big-endian的方式存在起始地址0x00002000中:| data |<-- address| 0x12 |<-- 0x00002000| 0x34 |<-- 0x00002001在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为例):bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 |-----MSB-----------------------------------LSBval | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |+-----------------------------------------+= 0x8 B 8 A1.1.2 小端模式(little-endian):LSB存放在最低端的地址上。

举例,双字节数0x1234以little-endian的方式存在起始地址0x00002000中:| data |<-- address| 0x34 |<-- 0x00002000| 0x12 |<-- 0x00002001在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如下(仍以双字节数0x8B8A为例):bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0 |-----MSB-----------------------------------LSBval | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |+-----------------------------------------+= 0x8 B 8 A1.2 数组在大端小端情况下的存储以unsigned int value = 0x12345678 为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:Big-Endian: 低地址存放高位,如下:高地址---------------buf[3] (0x78) -- 低位buf[2] (0x56)buf[1] (0x34)buf[0] (0x12) -- 高位---------------低地址Little-Endian: 低地址存放低位,如下:高地址---------------buf[3] (0x12) -- 高位buf[2] (0x34)buf[1] (0x56)buf[0] (0x78) -- 低位--------------低地址1.3 大端小端转换方法Big-Endian转换成Little-Endian如下:#define BigtoLittle16(A) ((((uint16)(A) & 0xff00) >> 8) | \(((uint16)(A) & 0x00ff) << 8))#define BigtoLittle32(A) ((((uint32)(A) & 0xff000000) >> 24) | \ (((uint32)(A) & 0x00ff0000) >> 8) | \(((uint32)(A) & 0x0000ff00) << 8) | \(((uint32)(A) & 0x000000ff) << 24))1.4 大端小端检测方法如何检查处理器是big-endian还是little-endian?联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写:int checkCPUendian(){union{unsigned int a;unsigned char b;} un;c.a = 1;return (c.b == 1);}2. 网络字节顺序2.1 概述> 字节内的比特位不受这种顺序的影响比如一个字节 1000 0000 (或表示为十六进制80H)不管是什么顺序其内存中的表示法都是这样。

> 大于1个字节的数据类型才有字节顺序问题比如 Byte A,这个变量只有一个字节的长度,所以根据上一条没有字节顺序问题。

所以字节顺序是“字节之间的相对顺序”的意思。

> 大于1个字节的数据类型的字节顺序有两种比如 short B,这是一个两字节的数据类型,这时就有字节之间的相对顺序问题了。

网络字节顺序是“所见即所得”的顺序。

而Intel类型的CPU的字节顺序与此相反。

比如上面的 short B=0102H(十六进制,每两位表示一个字节的宽度)。

所见到的是“0102”,按一般数学常识,数轴从左到右的方向增加,即内存地址从左到右增加的话,在内存中这个 short B的字节顺序是:01 02这就是网络字节顺序。

所见到的顺序和在内存中的顺序是一致的!而相反的字节顺序就不同了,其在内存中的顺序为:02 01假设通过抓包得到网络数据的两个字节流为:01 02如果这表示两个 Byte类型的变量,那么自然不需要考虑字节顺序的问题。

如果这表示一个 short 变量,那么就需要考虑字节顺序问题。

根据网络字节顺序“所见即所得”的规则,这个变量的值就是:0102假设本地主机是Intel类型的,那么要表示这个变量,有点麻烦:1) 定义变量 short X,2) 字节流地址为:pt,按顺序读取内存是为 X = *( (short*)pt );那么 X 的内存顺序当然是 01 02 (cheney注:这里应该为 02 01 才对吧)按非“所见即所得”的规则,这个内存顺序和看到的一样显然是不对的,所以要把这两个字节的位置调换。

调换的方法可以自己定义,但用已经有的API还是更为方便。

2.2 网络字节顺序(NBO)与主机字节顺序(HBO)网络字节顺序 NBO(Network Byte Order):按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。

主机字节顺序(HBO,Host Byte Order):不同的机器HBO不相同,与CPU 设计有关计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。

Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换。

htonl()简述:将主机的无符号长整形数转换成网络字节顺序。

#include <winsock.h>u_long PASCAL FAR htonl( u_long hostlong);hostlong:主机字节顺序表达的32位数。

注释:本函数将一个32位数从主机字节顺序转换成网络字节顺序。

返回值:htonl()返回一个网络字节顺序的值。

inet_ntoa()简述:将网络地址转换成“.”点隔的字符串格式。

#include<winsock.h>char FAR* PASCAL FAR inet_ntoa( struct in_addr in);in:一个表示Internet主机地址的结构。

本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。

请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。

应用程序不应假设该内存是如何分配的。

在同一个线程的下一个WIND OWS套接口调用前,数据将保证是有效。

返回值:若无错误发生,inet_ntoa()返回一个字符指针。

否则的话,返回NULL。

其中的数据应在下一个WINDOWS套接口调用前复制出来。

2.3 结束语网络中传输的数据有的和本地字节存储顺序一致,而有的则截然不同,为了数据的一致性,就要把本地的数据转换成网络上使用的格式,然后发送出去,接收的时候也是一样的,经过转换然后才去使用这些数据,基本的库函数中提供了这样的可以进行字节转换的函数,如和 htons( ) htonl( ) ntohs( ) ntohl() 。

这里n表示network,h表示host。

htons(), htonl() 用于本地字节向网络字节转换的场合,同样ntohs(), ntohl() 用于网络字节向本地格式转换的场合。

(s表示short,即对2字节操作,l表示long即对4字节操作)参考资料:/blog/static/135126900201022133 740759/。

相关文档
最新文档