网络字节与大小端
字节序分为大端字节序和小端字节序
现代PC大多采用小端字节序,所以小端字节序又被称为主机字节序。
大端字节序也称为网络字节序。
大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处。
小端模式是指低字节数据存放在低地址处,高字节数据放在高地址处。
通过对大小端的存储原理分析可发现,对于 char 型数据,由于其只占一个字节,所以不存在这个问题,这也是一般情况下把数据缓冲区定义成 char 类型 的原因之一。对于 IP 地址、端口号等非 char 型数据,必须在数据发送到网络上之前将其转换成大端模式,在接收到数据之后再将其转换成符合接收端主机的存储模式。
大小端转换
#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
#define htons(A) (A)
#define htonl(A) (A)
#define ntohs(A) (A)
#define ntohl(A) (A)
#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#define htons(A) ((((uint16_t)(A) & 0xff00) >> 8 ) | \\
(((uint16_t)(A) & 0x00ff) << 8 ))
#define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \\
(((uint32_t)(A) & 0x00ff0000) >> 8 ) | \\
(((uint32_t)(A) & 0x0000ff00) << 8 ) | \\
(((uint32_t)(A) & 0x000000ff) << 24))
#define ntohs htons
#define ntohl htohl
#else
#error Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both.
#endif
Linux 系统为大小端模式的转换提供了 4 个函数,输入 man byteorder 命令可得函数原型:
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
htonl 表示 host to network long ,用于将主机 unsigned int 型数据转换成网络字节顺序;
htons 表示 host to network short ,用于将主机 unsigned short 型数据转换成网络字节顺序;
ntohl、ntohs 的功能分别与 htonl、htons 相反。
判断大小端
#include <iostream>
using namespace std;
union myunion
{
int i;
char j;
};
int isLittleEndian_1(void)
{
myunion test;
test.i = 1;
return (test.i == test.j);
}
int isLittleEndian_2(void)
{
int i =1;
if (*((char *)&i) == 1) {
return 1;
}
return 0;
}
int isLittleEndian_3(void)
{
unsigned int i =0X1234;
if (*((char *)&i) == 0X34) {
return 1;
}
return 0;
}
int main(int argc, char const *argv[])
{
/* 系统大小端测试1 */
if (isLittleEndian_1)
{
cout<<"当前系统是小端模式"<<endl;
}else {
cout<<"当前系统是大端模式"<<endl;
}
/* 系统大小端测试2 */
if (isLittleEndian_2)
{
cout<<"当前系统是小端模式"<<endl;
}else {
cout<<"当前系统是大端模式"<<endl;
}
/* 系统大小端测试3 */
if (isLittleEndian_3)
{
cout<<"当前系统是小端模式"<<endl;
}else {
cout<<"当前系统是大端模式"<<endl;
}
return 0;
}
结果:
xzj@xzj-VirtualBox:~/development_test/process/big_little_Endian$ ./run
当前系统是小端模式
当前系统是小端模式
当前系统是小端模式