我想知道如何在C中解析IPv6地址并将其转换为128位值?
因此需要将像1:22:333:aaaa:b:c:d:e
这样的十六进制地址转换为其128位等效二进制数。问题是IP地址可以是::2
类型及其变体,因为它们是有效的IPv6地址。
输入来自键盘,因此是ASCII格式。
答案 0 :(得分:13)
您可以使用POSIX inet_pton
将字符串转换为struct in6_addr
。
#include <arpa/inet.h>
...
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?
}
答案 1 :(得分:9)
getaddrinfo()
可以理解IPv6地址。在提示中将AF_INET6传递给它,以及AI_NUMERICHOST(以防止DNS查找)。 Linux拥有它,Windows在Windows XP中拥有它。
答案 2 :(得分:2)
要在C中解析IPv6,您需要自己构建一个实用程序函数,该函数用于标记化字符串(十六进制块的冒号和子网位的正斜杠)。
答案 3 :(得分:2)
您可以使用getaddrinfo()
POSIX功能。它比inet_pton()
更灵活,例如它可以自动检测IPv4和IPv6地址格式,甚至可以解析主机名(使用DNS解析)和端口/服务名称(使用/etc/services
)。
#include <sys/types.h>
#include <netdb.h>
#include <netdb.h>
....
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
}
答案 4 :(得分:0)
在Windows中,您可以使用自Windows 2000以来可用的WSAStringToAddress
。
答案 5 :(得分:0)
Rosetta提供多种语言的样本:https://rosettacode.org/wiki/Parse_an_IP_Address
答案 6 :(得分:0)
如果你可以使用boost,那么这样的事情应该有效:
#include<boost/asio.hpp>
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特定功能更便携。