网络传输大小端问题
网络传输大小端问题
我们在边写linux网络编程的时候经常会使用htonl htons等函数用来对int类型 long类型的数据进行本地字节序和网络字节序的转换,而对于字符串类型的数据,就不需要转换呢?
- 网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?其实是按照传输数据的内存地址由低到高来进行传输的。
在验证上面这一个问题之前,先来看一下大小端的问题
- 小端字节序是我们比较常见的字节序,个人使用的x86计算机大部分使用小端字节序,其实很好理解,小端法(Little-Endian)就是低位字节排放在内存的低地址端(即该值的起始地址),高位字节排放在内存的高地址端;
- 大端法(Big-Endian)就是高位字节排放在内存的低地址端(即该值的起始地址),低位字节排放在内存的高地址端
- 就比如 0x12345678 这个十六进制数字,低位在最右边(理解一下十进制中12345678,从右往左是不是个十百千…),小端存储法就是0x78在低地址,0x12在高地址;大端0x78在高地址,0x12在低地址,可以用下面这一段代码看看自己是不是小端字节序.
1 |
|
- 输出结果是:78 56 34 12,证明了我使用的这台计算机是小端字节序
那么字符串在内存中存储形式是怎么样的呢?
- 比如”Hello”这个字符串,在内存中则是按照字符串本身从左往右顺序存储,’H’在前,’o’在后。这个则没必要写代码来验证了,太简单…
有了以上基础知识,那么便可以说明第一个问题了
- 网络上传输数据是按内存地址从低到高按顺序传输,那么传输”Hello”这个字符串的时候,就是按照”H” “e” “l” “l” “o”的顺序依次传输,对方接收的话,也是按照这个顺序把数据存入缓存区,字符串不涉及到大小端存储的规则,所以无需调用字节序转换函数来处理。
- 如果是 0x12345678 这个数据,那么则是按照0x78 0x56 0x34 0x12这个顺序按字节发送(16进制2位则是一个字节),对方机器如果收到后用int类型来解释这个数据,如果对方机器是小端字节序,那么没问题,收到的数据还是0x12345678,但是如果对方机器是大端字节序,用int来解释则会把高地址数据放在低位 低地址放在高位,变成了0x78563412,就会发生不想要的结果。
结论
- 所以在字节序相同的平台时间传输数据,进行转换字节序是没必要的,而在不同平台之间,则一定要进行转换