1.基本理论
- 计算机发送数据从内存低地址开始.
- 计算机接收数据的保存从低地址开始.
2.非数值型网络数据传输
如上图例子所示,发送端发送了四个字节内容,分别为0x12,0x34,0x56,0x78,假设这四个字节不表示数值例如unsigned int,而是图片内容数据。发送端从低内存地址开始发送四个字节,接收端将接收到的数据按照内存从低到高存储,这样完全没有问题,并不涉及字节序。
3.数值型数据存储
如上图所示,如果内存中的四个字节表示一个unsigned int类型整数,那么该整数值为多少呢?在不同类型计算机上可能表示数值不一样,0x12345678或者0x78563412.
如上图所示,如果计算机CPU架构是大端字节序:数值的高字节存储在内存的低位,则表示0x12345678;如果计算机CPU架构是小端字节序:数值的高字节存储在内存的高位,则表示0x78563412.如果传输的是数值型数据,网络传输层协议要求先发送数值的高字节,即低内存地址存储数值的高位,也就是大端字节序。平时常说的网络字节序就是大端字节序。另外,字节序只有在传输数值型数据时才会用到,所以网络开发中只有IP地址、端口等信息会需要字节序转化,其它数据并不需要。
4.字节序转换
下面我们着重讨论下传输数值型数据时的字节序转换。既然网络固定用大端字节序,那么发送端和接收端就要考虑到字节序转换问题。
如上图左侧所示,发送端如果是小端字节序,实际想要发送的是val=0x78563412,但是低内存是0x12,不满足网络传输层的要求"先发送数值的高位",经过htonl转换,生成新数newVal=0x12345678,实际发送newVal,满足传输层要求。
如上图右侧所示,发送端如果是大端字节序,实际想要发送的是val=0x12345678,低内存是0x12,满足网络传输层的要求"先发送数值的高位"。实际开发中不管当前是大端还是小端都会做转换,经过ntohl转化为网络字节序,生成新数newVal还是等于0x12345678。
如上图所示,接收端收到0x12,0x34,0x56,0x78后,不管本机是大端还是小端字节序,经过htonl转换得到0x12345678这个值,即将低内存的0x12作为数值的高字节.
5.转换代码
htonl和ntohl实现原理一样,都是将低内存的内容作为数值的高字节,将高内存的内容作为数值的低字节,形成一个数值。unsigned int myhtonl(const unsigned int val){unsigned char tempCh[4]={0};memcpy(tempCh,&val,sizeof(val));unsigned int res=0;res = (((unsigned int)tempCh[0])<<24) | (((unsigned int)tempCh[1])<<16) | (((unsigned int)tempCh[2])<<8) | ((unsigned int)tempCh[3]);return res;}