大小端转换函数
字数
1034 字
阅读时间
5 分钟
上一节内容:socket编程 下一节内容:
一、字节序
顾名思义,就是一个字节类型的数据在内存中的存放顺序。 对于单个字节来说是不存在字节序问题的
二、大端存储方式和小端存储方式
- 主机字节序(小端)
- 数据的
低位字节(例如:0x123456,56就是低位字节)存储到内存的低地址位,数据的高位字节(例如:0x123456,12就是低位字节)存储到内存的高地址位- 口诀:低低,高高
- 我们使用的PC机,数据的存储默认使用的是小端
- 数据的
- 网络字节序(大端)
- 数据的
低位字节(例如: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被写入到这块内存中
- af: 地址族(IP地址的家族包括ipv4和ipv6)协议
- 返回值:成功返回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指向的内存中最多可以存储多少个字节
- af: 地址族协议
返回值:
- 成功: 指针指向第三个参数对应的内存地址, 通过返回值也可以直接取出转换得到的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);