对字节序的定义:查看维基百科字条
大概的意思就是:
- 大端序中,高位字节放在低位地址
- 小端序中,低位字节放在低位地址
#include <arpa/inet.h>
#include <iostream>
#include <sys/socket.h>
using namespace std;
int main()
{
const char* dot_addr = "103.7.28.136";
in_addr_t addr;
inet_pton(dot_addr, &addr);
cout << addr.s_addr << endl;
return 0;
}
输出:2283538279
本机的主机字节序是小端序
inet_pton
转化点分地址成网络序的in_addr_t
(实际上是个整型)的数据。
实际上,103.7.28.136 这个IP的二进制数据应该是:1100111000001110001110010001000
,也就是十进制的1728519304
,十六进制的67071C88
由于inet_pton
转成网络序的,所以在内存中这个二进制串的存储就是这么表示的(用十六进制展示),记住在原数据67071C88
中,67是高位字节
按内存从低到高存储:高位字节放在低位地址
低位 | - | - | 高位 |
---|---|---|---|
67 | 07 | 1C | 88 |
而作为小端序的主机,面对这在内存中字节,自然就会解析成881C0767
,因为在小端序看来,低位地址的字节属于低位字节。
而十六进制881C0767
就是十进制的2283538279
,也就是我们的输出
网络字节序
一般来说,我们不用在传输数据的时候做大小端的转换,因为系统会自动帮我们把数据变成网络字节序(也即是大端序)。
在网络传输中大端序的含义是:先传输高位字节。可以这么理解,大端序中高位字节存放在低位地址,而CPU按地址从低到高读取数据然后发送,所以先传送数据的高位字节。
这个和主机序是什么模式没有关系,如果主机是大端序,那就正常读取传输,如果主机的小端序,系统就自动帮我们做一次大小端转换,然后传输。反映在代码里是这样:
int data = 0x12345678;
int ret = send(sockfd, &data, sizeof(data), 0)
大小端的转换对于我们来说是透明的。比如在小端主机中,由于78
存储在低地址,本来应该先被传输,由于系统在send的时候会自动帮我们对缓冲区的数据做一次大小端转换,先输出的就变成了12
了。
同样,在接收端,从网络接收到的字节流,由于先接收到的是数据的高位字节,系统会根据我们主机的字节序来判断这个字节应该放在缓冲区的高位地址还是低位地址。所以我猜这也是为什么我们要提供缓冲区地址和缓冲区长度的原因吧。
网友评论