我们在本文中已经分析了网络通信中,为保持报文顺序一致,而需要进行字节序转换。
本文对字节序转换再进行分析:
quint16 wCRC = 0xAA01;
uchar* pSendBuf = (uchar*)malloc(2 * sizeof(uchar));
memcpy(pSendBuf, &wCRC, sizeof(quint16));//memcpy会按照主机序将字节拷贝到内存中
printf("pSendBuf[0]:%02x\n",pSendBuf[0]);//01
printf("pSendBuf[1]:%02x\n",pSendBuf[1]);//aa
quint16 value = *(quint16*)(pSendBuf);//直接取的话,也会按照主机字节序来取
printf("memcpy:%04x\n",value);//aa01
quint16 value_1 = htons(value);//主机字节序转换成网络字节续
printf("htons:%04x\n",value_1);//01aa
quint16 value_2 = ntohs(value);
printf("ntohs:%04x\n",value_2);
fflush(stdout);
分析:
1)由pSendBuf[0],存储的时01,pSendBuf[1]存储的是AA,我们可以知道本机字节序是小端法排序
2)htons(value)之后,转化为网络字节序(大端法排序),故字节顺序肯定颠倒了。
3)ntohs(value)之后,网络字节续(大端法排序)转为为主机字节序(小端法排序),故字节顺序肯定颠倒。
小结:
网络字节序是大端序,这个时固定的!
主机序可能是大端序,也可能是小端序,当是大端序时,htons,ntohs,不起作用;
当是小端序时,htons会交换quint16 两个字节位置。(小端转大端)
ntohs也会交换quint16两个字节位置,效果同htons,可以通过上述的示例,htons、ntohs结果都是aa01验证。(大端转小端)
再分析:
网络编程中,为保证发送端和接收端字节序保持一致,以发送的报文0xAA01为例,
我们在发送端使用htons(),保证报文中存储的是0xAA ,0x01;
我们在接收端使用ntohs(),保证将报文中0xAA,0x01转换为主机字节序(假设,接收端主机是大端,那么调用ntohs未起作用,假设接收端主机是小端,通过quint16_t强转后,变为01AA, 再次调用ntohs后,字节转换变为AA01)
结论:
1)当主机是小端法排序时,无论使用htons还是ntohs都会将uint16_t的两个字节转换位置。由本文知,二者其实是同一个宏。
2)网络编程中,使用htons和ntohs,都是为了将字节序转为大端序,发送端htons(),转为大端序,memcpy到报文中发送;
接收端通过 uint16_t取出后,经过ntohs()转换为大端序。