欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > C++网络编程之字节序

C++网络编程之字节序

2024/10/23 15:33:14 来源:https://blog.csdn.net/hope_wisdom/article/details/143066566  浏览:    关键词:C++网络编程之字节序

概述

        字节序是指多字节数据在内存中的存储顺序。主要有两种字节序:大端序、小端序。

        大端序:即Big-Endian,高位字节存放在低地址处,低位字节存放在高地址处。比如:16位整数0x1234,在大端序下会以0x12 0x34的形式存储。

        小端序:即Little-Endian,低位字节存放在低地址处,高位字节存放在高地址处。比如:16位整数0x1234,在小端序下会以0x34 0x12的形式存储。

        需要注意的是:不同计算机系统可能使用不同的字节序来存储多字节的数据类型。当这些系统之间进行通信时,如果不正确处理字节序问题,就可能会导致数据解析错误。比如:如果一台机器是小端序,另一台是大端序,它们之间的数据交换如果没有经过适当的转换,接收方可能会误解发送方的数据。

检测字节序

        在C++中,检测字节序有几种不同的方法。下面,分别进行介绍。

        1、使用类型转换。下面的代码封装了一个IsLittleEndian的函数,用于判断是否为小端序。在该函数中,首先初始化一个32位无符号整数uiValue,其值为0x01020304。然后,使用reinterpret_cast将uiValue的地址转换为char*类型的指针,以便逐字节访问。检查uiValue的第一个字节是否为0x04,如果是,则系统是小端序;否则,系统是大端序。

#include <iostream>
using namespace std;bool IsLittleEndian()
{unsigned int uiValue = 0x01020304;char* pValue = reinterpret_cast<char*>(&uiValue);// 如果第一个字节是0x04,则是小端序return (pValue[0] == 0x04);
}int main()
{if (IsLittleEndian()){cout << "Little-Endian" << endl;}else{cout << "Big-Endian" << endl;}return 0;
}

        2、使用联合体。联合体允许我们在相同的内存位置存储不同的数据类型,这样可以方便地检查多字节数据类型的字节顺序。在下面的代码中,我们首先使用联合体将一个32位无符号整数unsigned int i和一个4个字符的数组char c[4]共享同一块内存。然后,初始化联合体中的unsigned int i为0x01020304。最后,通过char c[4]访问unsigned int i的第一个字节。检查第一个字节是否为0x04,如果是,则系统是小端序;否则,系统是大端序。

#include <iostream>
using namespace std;bool IsLittleEndian()
{union {unsigned int i;char c[4];} value = {0x01020304};// 如果第一个字节是0x04,则是小端序return (value.c[0] == 0x04);
}int main()
{if (IsLittleEndian()){cout << "Little-Endian" << endl;}else{cout << "Big-Endian" << endl;}return 0;
}

        3、使用标准库函数。在某些情况下,可以使用标准库提供的函数来检测字节序。比如:在POSIX兼容的系统中,可以使用endian.h头文件中的宏来检测字节序。具体如何使用,可参考下面的示例代码。

#include <iostream>
#include <endian.h>
using namespace std;int main()
{
#if __BYTE_ORDER == __LITTLE_ENDIANcout << "Little-Endian" << endl;
#elif __BYTE_ORDER == __BIG_ENDIANcout << "Big-Endian" << endl;
#elsecout << "Unknown endianness" << endl;
#endifreturn 0;
}

主机字节序与网络字节序

        主机字节序是指当前计算机系统中,多字节数据类型的存储顺序。主要有上面介绍的两种字节序:大端序和小端序。

        在网络协议中,为了确保数据的一致性,通常规定使用一种统一的字节序。最常见的网络字节序是大端序,这是因为:大端序与人类阅读数字的习惯一致,便于调试和理解。比如:在TCP/IP协议族中,所有多字节的数据类型都要求使用大端序进行传输。

字节序转换

        在跨平台或异构网络环境中,不同的系统可能使用不同的字节序。如果发送方和接收方的字节序不一致且没有进行适当的转换,会导致数据解析错误。因此,在网络编程中,必须确保数据在发送前转换为网络字节序,在接收后转换回主机字节序。

        C++标准库提供了几个用于字节序转换的函数。对于POSIX兼容系统(比如:Linux、Mac等),这些函数定义在arpa/inet.h头文件中。对于Windows系统,这些函数定义在winsock2.h头文件中。

        htons()和htonl():用于将主机字节序转网络字节序(Host to Network Short/Long)。

        ntohs()和ntohl():用于将网络字节序转主机字节序(Network to Host Short/Long)。

        在下面的示例代码中,我们使用htons和htonl将主机字节序的hostShort、hostLong转换成了网络字节序的netShort、netLong。然后,再将网络字节序的netShort、netLong转换回主机字节序的convertedShort、convertedLong。注意:在Windows下使用Visual Studio编译这段程序时,需要在工程中链接ws2_32.lib库,否则链接时会报错。

#include <iostream>
#include <winsock2.h>
using namespace std;int main()
{// 主机字节序转为网络字节序uint16_t hostShort = 0x1234;uint32_t hostLong = 0x12345678;uint16_t netShort = htons(hostShort);uint32_t netLong = htonl(hostLong);cout << "Host short: " << hex << hostShort << endl;cout << "Network short: " << hex << netShort << endl;cout << "Host long: " << hex << hostLong << endl;cout << "Network long: " << hex << netLong << endl;// 再将网络字节序转回主机字节序uint16_t convertedShort = ntohs(netShort);uint32_t convertedLong = ntohl(netLong);cout << "Converted short: " << hex << convertedShort << endl;cout << "Converted long: " << hex << convertedLong << endl;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com