在网络编程中,我们经常需要处理 IP 地址和端口号等数据,这些数据需要在主机字节序(Host Byte Order)与网络字节序(Network Byte Order)之间进行转换。
什么是字节序?
字节序指的是多字节数据在内存中的存储顺序。
-
主机字节序:不同的主机可能使用不同的字节序,如:
-
小端序(Little Endian):低字节在前,高字节在后(如 x86 架构)。
-
大端序(Big Endian):高字节在前,低字节在后。
-
为了确保数据在网络传输中的一致性,我们需要进行字节序转换。
inet_ntoa
作用
inet_ntoa
将一个网络字节序的 IPv4 地址(二进制形式)转换为点分十进制字符串,方便人类阅读。
函数原型
#include <arpa/inet.h> // Linux/Unix
#include <winsock2.h> // Windows
char *inet_ntoa(struct in_addr in);
参数
-
in
:一个struct in_addr
类型的值,表示一个网络字节序的 IPv4 地址。
返回值
-
返回一个指向静态分配内存的字符串,表示点分十进制的 IPv4 地址。
示例
#include <stdio.h>
#include <arpa/inet.h>int main() {struct in_addr addr;addr.s_addr = htonl(0x7F000001); // 127.0.0.1 的网络字节序char *ip_str = inet_ntoa(addr);printf("IP 地址: %s\n", ip_str); // 输出:IP 地址: 127.0.0.1return 0;
}
注意事项
-
inet_ntoa
返回的字符串是静态分配的,因此多次调用会覆盖之前的结果。 -
仅支持 IPv4,不支持 IPv6。
htonl
作用
htonl
(Host TO Network Long)将一个主机字节序的 32 位整数转换为网络字节序。
函数原型
#include <arpa/inet.h> // Linux/Unix
#include <winsock2.h> // Windows
uint32_t htonl(uint32_t hostlong);
参数
-
hostlong
:一个 32 位整数(如 IPv4 地址或其他网络数据)。
返回值
-
返回
hostlong
转换为网络字节序后的值。
示例
#include <stdio.h>
#include <arpa/inet.h>int main() {uint32_t host_long = 0x7F000001; // 127.0.0.1 的主机字节序uint32_t net_long = htonl(host_long);printf("主机字节序: 0x%x\n", host_long); // 输出:主机字节序: 0x7f000001printf("网络字节序: 0x%x\n", net_long); // 输出:网络字节序: 0x0100007freturn 0;
}
应用场景
相关函数
inet_aton
作用
inet_aton
将一个点分十进制字符串表示的 IPv4 地址转换为网络字节序的二进制形式。
函数原型
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
参数
-
cp
:点分十进制字符串,如 "127.0.0.1"。 -
inp
:指向struct in_addr
的指针,用于存储转换后的网络字节序地址。
返回值
-
成功返回非零,失败返回 0。
示例
#include <stdio.h>
#include <arpa/inet.h>int main() {struct in_addr addr;if (inet_aton("127.0.0.1", &addr)) {printf("网络字节序: 0x%x\n", addr.s_addr);} else {printf("转换失败\n");}return 0;
}
ntohl
作用
ntohl
(Network TO Host Long)将一个网络字节序的 32 位整数转换为主机字节序。
示例
#include <stdio.h>
#include <arpa/inet.h>int main() {uint32_t net_long = 0x0100007f;uint32_t host_long = ntohl(net_long);printf("主机字节序: 0x%x\n", host_long);return 0;
}
htons
和 ntohs
作用
-
htons
(Host TO Network Short):将主机字节序的 16 位整数转换为网络字节序。 -
ntohs
(Network TO Host Short):将网络字节序的 16 位整数转换为主机字节序。
示例
#include <stdio.h>
#include <arpa/inet.h>int main() {uint16_t port = 8080;uint16_t net_port = htons(port);printf("网络字节序端口: 0x%x\n", net_port);uint16_t host_port = ntohs(net_port);printf("主机字节序端口: %u\n", host_port);return 0;
}
inet_ntop
和 inet_pton
作用
示例
#include <stdio.h>
#include <arpa/inet.h>int main() {char str[INET6_ADDRSTRLEN];struct in6_addr ipv6_addr;// IPv6 字符串 -> 网络字节序inet_pton(AF_INET6, "::1", &ipv6_addr);// 网络字节序 -> IPv6 字符串inet_ntop(AF_INET6, &ipv6_addr, str, INET6_ADDRSTRLEN);printf("IPv6 地址: %s\n", str);return 0;
}
总结
函数 | 作用 | 应用场景 |
---|---|---|
inet_ntoa | 网络字节序 IPv4 转为点分十进制字符串 | 输出人类可读的 IP 地址 |
inet_aton | 点分十进制字符串转为网络字节序 IPv4 | 输入 IP 地址 |
htonl | 主机字节序 32 位整数转为网络字节序 | 发送数据前 |
ntohl | 网络字节序 32 位整数转为主机字节序 | 接收数据后 |
htons | 主机字节序 16 位整数(端口号)转为网络字节序 | 发送数据前 |
ntohs | 网络字节序 16 位整数(端口号)转为主机字节序 | 接收数据后 |