C中的IPv6解析

我想知道如何在C中解析IPv6地址并将其转换为128位值?

所以hex地址如1:22:333:aaaa:b:c:d:e需要转换为128位等效二进制。 问题是IP地址可能是类型::2及其变体,因为它们是有效的IPv6地址。

输入来自键盘,因此是ASCII格式。

您可以使用POSIX inet_pton将字符串转换为struct in6_addrstruct in6_addr

 #include  ... const char *ip6str = "::2"; struct in6_addr result; if (inet_pton(AF_INET6, ip6str, &result) == 1) // success! { //successfully parsed string into "result" } else { //failed, perhaps not a valid representation of IPv6? } 

getaddrinfo()可以理解IPv6地址。 在提示中将AF_INET6传递给它,以及AI_NUMERICHOST(以防止DNS查找)。 Linux拥有它,Windows在Windows XP中拥有它。

要在C中解析IPv6,您需要自己构建一个实用程序函数,该函数用于标记化字符串(hex块的冒号和子网位的正斜杠)。

  1. 将原始IPv6字符串标记为较小的子字符串。
  2. 将非空子字符串转换为hex块。 (ASCII到十进制转换)
  3. 通过在前面填充零来将hex块扩展为2个字节。 (只有前导零被修剪)
  4. 完整IPv6应具有8个hex块,计算丢失的hex块。 (零分组只能发生一次)
  5. 重新插入缺少的hex块。 (使用空子串的索引)

您可以使用getaddrinfo() POSIX函数。 它比inet_pton()更灵活,例如它自动检测IPv4和IPv6地址格式,它甚至可以解析主机名(使用DNS解析)和端口/服务名称(使用/etc/services )。

 #include  #include  #include  .... const char *ip6str = "::2"; struct sockaddr_storage result; socklen_t result_len; struct addrinfo *res = NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_DEFAULT | AI_NUMERICHOST | AI_NUMERICSERV; rc = getaddrinfo(ip6str, NULL, &hints, &res); if (rc != 0) { fprintf(stderr, "Failure to parse host '%s': %s (%d)", ip6str, gai_strerror(rc), rc); return -1; } if (res == NULL) { // Failure to resolve 'ip6str' fprintf(stderr, "No host found for '%s'", ip6str); return -1; } // We use the first returned entry result_len = res->ai_addrlen; memcpy(&result, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); 

IPv6地址存储在struct sockaddr_storage result变量中。

 if (result.ss_family == AF_INET6) // Ensure that we deal with IPv6 { struct sockaddr_in6 * sa6 = (struct sockaddr_in6 *) &result; struct in6_addr * in6 = &sa6->sin6_addr; in6->s6_addr[0]; // This is a first byte of the IPv6 in6->s6_addr[15]; // This is a last byte of the IPv6 } 

在Windows中,您可以使用自Windows 2000以来可用的WSAStringToAddress

Rosetta提供多种语言的样本: https : //rosettacode.org/wiki/Parse_an_IP_Address

如果你可以使用boost,这样的东西应该工作:

 #include using boost::asio::ip; bool parseIpv6String(std::string ipv6_string, char* dest){ try{ address_v6 addr = address_v6::from_string(ipv6_string); memcpy(dest,addr.to_bytes().data(), 16); }catch(...){ return false; } return true; } 

它比POSIX特定function更便携。