网络字节与大小端

字节序分为大端字节序和小端字节序

现代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 相反。

判断大小端

typedef union {
    int i;
    char c;
}my_union;
int isLittleEndian(void)
{
    my_union u;
    u.i = 1;
    return (u.i == u.c);
}
int main()
{
    //系统大小端测试
    if (isLittleEndian())
        printf("is Little Endian!\n");
    else
        printf("is big endian!\n");
    return 0;
}

详解大端模式和小端模式

猜你喜欢

转载自www.cnblogs.com/xzj8023tp/p/11302273.html