C++实现主机字节序和网络字节序转换示例
作者:点墨
这篇文章主要为大家介绍了C++实现主机字节序和网络字节序转换示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
字节序问题
现代CPU一次至少能装载4字节(32位机),即一个整数,这4个字节在内存中的排列顺序将影响它的值。这就是字节序问题。字节序分为大端字节序(big endian)和小端字节序(little endian)。
如上图,大端字节序是指数据的高位存在内存的低地址处,小端字节序是指数据的高位存在内存的高地址处。
现代PC大多采用小端字节序
当格式化的数据需要在两台使用不同字节序的主机进行传递时,接收端会错误的处理。解决的方法是:发送端将发送的数据转换成大端字节序然后发送,接收端根据自己的字节序决定需不需要处理(小端转换,大端不处理)。
在做网络编程的时候,使用提供的库即可进行转换(linux库,windows下是一样的,头文件有所区别)
#include <netinet/in.h> unsigned long int _htonl(unsigned long int hostlong); unsigned short int _htons(unsigned short int hostshort); unsigned long int _ntohl(unsigned long int netlong); unsigned short int _ntohs(unsigned short int netshort);
互换数据
如果平台没有提供这套,那么可以自己实现一下,原理很简单,就是互换下数据
#include <stdint.h> #define BigLittleSwap16(v) ((0xFF00 & (uint16_t)(v)) >> 8 | (0x00FF & (uint16_t)(v)) << 8) #define BigLittleSwap32(v) ((0xFF000000 & (uint32_t)(v)) >> 24 | (0x00FF0000 & (uint32_t)(v)) >> 8 | (0x0000FF00 & (uint32_t)(v)) << 8 | (0x000000FF & (uint32_t)(v)) << 24) #define BigLittleSwap64(v) ((0xFF00000000000000 & (uint64_t)(v)) >> 56 |(0x00FF000000000000 & (uint64_t)(v)) >> 40 |(0x0000FF0000000000 & (uint64_t)(v) )>> 24 |(0x000000FF00000000 & (uint64_t)(v)) >> 8 |(0x00000000FF000000 & (uint64_t)(v)) << 8| (0x0000000000FF0000 & (uint64_t)(v)) << 24 | (0x000000000000FF00 & (uint64_t)(v) )<< 40 | (0x00000000000000FF & (uint64_t)(v) )<< 56 ) int isCPUBigEndian(){ union Data{ short val; char byte; } data; data.val = 0x0102; return (data.byte == 0x01); } unsigned long int _htonl(unsigned long int hostlong); unsigned short int _htons(unsigned short int hostshort); unsigned long int _ntohl(unsigned long int netlong); unsigned short int _ntohs(unsigned short int netshort); unsigned long int _htonl(unsigned long int hostlong){ return isCPUBigEndian() ? hostlong : BigLittleSwap32(hostlong); } unsigned short int _htons(unsigned short int hostshort){ return isCPUBigEndian() ? hostshort : BigLittleSwap16(hostshort); } unsigned long int _ntohl(unsigned long int netlong){ return isCPUBigEndian() ? netlong : BigLittleSwap32(netlong); } unsigned short int _ntohs(unsigned short int netshort){ return isCPUBigEndian() ? netshort : BigLittleSwap16(netshort); }
测试
#include <netinet/in.h> #include <stdio.h> int main(int argc,const char*argv[]){ long int v1 = 0x11223344; short int v2 = 0x1122; printf("the endian of system is:%s\n",isCPUBigEndian()?"Big Endian":"Little Endian"); printf("htonl:%x , %x , %x\n",v1,htonl(v1),_htonl(v1)); printf("htons:%x , %x , %x\n",v2,htons(v2),_htons(v2)); printf("ntohl:%x , %x , %x\n",v1,ntohl(v1),_ntohl(v1)); printf("ntohs:%x , %x , %x\n",v2,htons(v2),_htons(v2)); return 0; }
在linux下的测试结果如下图
以上就是C++实现主机字节序和网络字节序转换示例的详细内容,更多关于C++主机网络字节序转换的资料请关注脚本之家其它相关文章!