主机字节序和网络字节序
一、简介
在使用网络进行程序设计中会碰到的一个问题是字节序的问题,在基于单机或者同类型机器进行开发的过程中很少遇到。由于网络的他点是将 Internet 上不同的网络设备和主机进行连接和通信,这决定了使用网络进行开发的程序的特点就是要兼容各种类型的设备,其中的数据在不同的设备上要有唯一的含义。字节序的问题是上述情况下的典型问题。
二、字节序的含义
字节序的问题是由于 CPU 对整数在内存中的存放方式造成的。多于一个字节的数据类型在内存中的存放顺序叫 主机字节序。最常见的字节序有两种,小端字节序和大端字节序。
小端字节序 Little Endian(LE)
将数据的最低字节放在内存的起始位置。
小端字节序的特点是:内存地址较低的位存放数据的低位,内存地址高的位存放数据的高位,与习惯思维一致。
采用低字节序的CPU有x86架构的Intel系列产品。
大端字节序Big Endian(BE)
将数据的高字节存放在内存的起始位置。
大端字节序的特点是:内存中低字节位置存放数据的高位字节,内存中的高位字节存放数据的较低字节数据,与思维习惯不一致。
但是与实际数据的表达方式是一致的。
如果将内存中的数据直接放在文件中,打开文件查看会发现和原来的数据的高低位一致。
采用大端字节序的典型代表有PowerPC的UNIX系统。
例如,对于一个 8 位字节的数据 0x12345678,假设在内存中存放的开始地址为 0x1000,则在小端字节序和大端字节序系统中的方式如下:
内存地址 | 0x1000 | 0x1001 | 0x1002 | 0x1003 |
---|---|---|---|---|
小端字节序 | 0x78 | 0x56 | 0x34 | 0x12 |
大端字节序 | 0x12 | 0x34 | 0x56 | 0x78 |
而如果将 0x12345678 写入内存地址 0x1000 开始的地方,在内存中的值为如下:
内存地址 | 小端字节序 | 大端字节序 |
---|---|---|
0x1000 | 0x12 | 0x78 |
0x1001 | 0x34 | 0x56 |
0x1002 | 0x56 | 0x34 |
0x1003 | 0x78 | 0x12 |
系统对多字节数据的不同存放方法造成了使用方法的问题,例如,在 x86 系统主机A上的一个值为 0x12345678,数据通过网络传送到 PowerPC 上的一个运行UNIX的主机 B 上,在 B 上此值解释为 0x78563412,与原来的数据不同,这样就造成了传输上兼容性方面的困难。
三、网络字节序的转换
网络的字节序标准规定为大端字节序,不同平台上会对主机字节序进行转化后再进行传送,到主机后再转化为主机字节序,数据的传输就不会产生问题。同一个数据在不同平台上可以使用网络字节序的转换函数来实现。
如图5.31所示为主机A中的应用程序将变了a中的值0x12345678,通过网络传递给主机B中的应用程序中的变量b,如果不进行网络字节序转换,b 的值为 0x78563412
如图 5.32 所示,如果进行网络字节序转换,a 的值与 b 的值均为 0x12345678。 进行网络字节序转换的函数有 htons()、ntohs()、htonl()、ntohl() 等,其中 s 是 short 数据类型的意思,l 是 long 数据类型的意思,h 是 host 即主机的意思,n 是 network 即网络的意思。
- htons():表示对于short类型的变量,从主机字节许转换为网络字节序。
- ntohs():表示对于short类型的变量,从网络字节序转换为主机字节序。
- htonl():表示对于long类型的变量,从主机字节许转换为网络字节序。
- ntohl():表示对于long类型的变量,从网络字节序转换为主机字节序。
字节序的转换函数并没有转换符号类型变量,是否为符号类型是由应用程式来确定的,与字节无关。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论