Skip to content

大小端转换函数

字数
1034 字
阅读时间
5 分钟

上一节内容:socket编程 下一节内容:

一、字节序

顾名思义,就是一个字节类型的数据在内存中的存放顺序。 对于单个字节来说是不存在字节序问题的

二、大端存储方式和小端存储方式

  1. 主机字节序(小端)
    • 数据的低位字节(例如:0x123456,56就是低位字节)存储到内存的低地址位,数据的高位字节(例如:0x123456,12就是低位字节)存储到内存的高地址位
      • 口诀:低低,高高
    • 我们使用的PC机,数据的存储默认使用的是小端
  2. 网络字节序(大端)
    • 数据的低位字节(例如:0x123456,56就是低位字节)存储到内存的高地址位,数据的高位字节(例如:0x123456,12就是低位字节)存储到内存的低地址位
      • 口诀:低高,高低
    • 套接字通信过程中操作的数据都是大端存储的,包括:接收/发送的数据、IP地址、端口

三、大小端转换函数

如果不清楚某个函数的使用方法和作用,可以使用man [函数]命令查看离线文档

C
#include <arpa/inet.h>
// u:unsigned
// 16: 16位, 32:32位
// h: host, 主机字节序
// n: net, 网络字节序
// s: short
// l: int

// 这套api主要用于 网络通信过程中 IP 和 端口 的 转换
// 将一个短整形从主机字节序 -> 网络字节序
uint16_t htons(uint16_t hostshort);
// 将一个整形从主机字节序 -> 网络字节序
uint32_t htonl(uint32_t hostlong);

// 将一个短整形从网络字节序 -> 主机字节序
uint16_t ntohs(uint16_t netshort)
// 将一个整形从网络字节序 -> 主机字节序
uint32_t ntohl(uint32_t netlong);

四、IP地址转换

虽然IP地址本质是一个整形数,但是在使用的过程中都是通过一个字符串来描述,下面的函数描述了如何将一个字符串类型的IP地址进行大小端转换:

1. 方法一:inet_pton()

c
// 主机字节序的IP地址转换为网络字节序
// 主机字节序的IP地址是字符串, 网络字节序IP地址是整形
int inet_pton(int af, const char *src, void *dst);
  • 参数:
    • af: 地址族(IP地址的家族包括ipv4和ipv6)协议
      • AF_INET: ipv4格式的ip地址
      • AF_INET6: ipv6格式的ip地址
    • src: 传入参数, 对应要转换的点分十进制的ip地址: 192.168.1.100
    • dst: 传出参数, 函数调用完成, 转换得到的大端整形IP被写入到这块内存中
  • 返回值:成功返回1,失败返回0或者-1

2. 方法二:*inet_ntop()

c
#include <arpa/inet.h>
// 将大端的整形数, 转换为小端的点分十进制的IP地址        
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
  • 参数:

    • af: 地址族协议
      • AF_INET: ipv4格式的ip地址
      • AF_INET6: ipv6格式的ip地址
    • src: 传入参数, 这个指针指向的内存中存储了大端的整形IP地址
    • dst: 传出参数, 存储转换得到的小端的点分十进制的IP地址
    • size: 修饰dst参数的, 标记dst指向的内存中最多可以存储多少个字节
  • 返回值:

    • 成功: 指针指向第三个参数对应的内存地址, 通过返回值也可以直接取出转换得到的IP字符串
    • 失败: NULL

3. 方法三:inet_addr()

还有一组函数也能进程IP地址大小端的转换,但是只能处理ipv4的ip地址

c
// 点分十进制IP -> 大端整形
in_addr_t inet_addr (const char *cp);

// 大端整形 -> 点分十进制IP
char* inet_ntoa(struct in_addr in);

贡献者

The avatar of contributor named as freeway348 freeway348

文件历史

撰写