为了方便阅读,我们平时看到的是点分十进制的 IPv4 地址和以冒号分隔的 IPv6 地址。但是在网络上,编程里传输的不能是这两种形式,而是必须先转换为二进制形式,inet_pton() 函数所做的事情正是如此。函数定义如下:
[Plain Text] 纯文本查看 复制代码 #include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
第 1 个参数 af 要么是 AF_INET,要么是 AF_INET6,前者表示转换的是 IPv4 地址,后者表示转换的是 IPv6 地址。
第 2 个参数 src 可以是点分十进制的 IPv4 地址形式,也可以是以冒号分隔的 IPv6 地址形式。
第 3 个参数 dst 用来存储转换后的二进制形式。
测试代码:
[C++] 纯文本查看 复制代码 #include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
struct in_addr addr4;
struct in6_addr addr6;
int domain, s, i;
char str[INET6_ADDRSTRLEN];
if (argc != 3) {
fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
exit(EXIT_FAILURE);
}
domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
(strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
if (domain == 4 || domain == AF_INET) {
domain = AF_INET;
s = inet_pton(domain, argv[2], &addr4);
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
fprintf(stdout, "Network byte order: %u\n",addr4.s_addr);
}
else if (domain == 6 || domain == AF_INET6) {
domain = AF_INET6;
s = inet_pton(domain, argv[2], &addr6);
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
fprintf(stdout, "Network byte order: ");
for (i = 0; i < 16; i++)
fprintf(stdout, "%u ", addr6.__in6_u.__u6_addr8[i]);
printf ("\n");
}
else {
fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
exit(EXIT_FAILURE);
}
if (domain == AF_INET) {
if (inet_ntop(domain, &addr4, str, INET6_ADDRSTRLEN) == NULL) {
perror("inet_ntop");
exit(EXIT_FAILURE);
}
printf("%s\n", str);
} else if (domain == AF_INET6) {
if (inet_ntop(domain, &addr6, str, INET6_ADDRSTRLEN) == NULL) {
perror("inet_ntop");
exit(EXIT_FAILURE);
}
printf("%s\n", str);
}
exit(EXIT_SUCCESS);
}
代码中 INET6_ADDRSTRLEN 在netinet/in.h (该头文件由 arpa/inet.h 文件包含)文件中被定义为: #define INET6_ADDRSTRLEN 46 。
结构 struct in_addr 的定义为:
[C++] 纯文本查看 复制代码 /* Internet address. */
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
结构 struct in6_addr 定义为:
[C++] 纯文本查看 复制代码 /* IPv6 address */
struct in6_addr
{
union
{
uint8_t __u6_addr8[16];
#if defined __USE_MISC || defined __USE_GNU
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
#endif
} __in6_u;
#define s6_addr __in6_u.__u6_addr8
#if defined __USE_MISC || defined __USE_GNU
# define s6_addr16 __in6_u.__u6_addr16
# define s6_addr32 __in6_u.__u6_addr32
#endif
};
其中 uint8_t 被定义为 unsigned char 类型,如果要用 printf() 函数来打印该类型,格式控制符为 %u 。
运行输出:# ./inet_pton i6 1:0:0:0:0:0:0:8
Network byte order: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 8
1::8
# ./inet_pton i6 0:0:0:0:0:FFFF:204.152.189.116
Network byte order: 0 0 0 0 0 0 0 0 0 0 255 255 204 152 189 116
::ffff:204.152.189.116
# ./inet_pton i4 184.22.147.23
Network byte order: 395515576
184.22.147.23 关于 IPV6 的地址记录介绍可参考:《IPv6 记法 》。 |