C语言 C 语言中的 IPv6 解析

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2962664/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:33:58  来源:igfitidea点击:

IPv6 parsing in C

cparsingipv6

提问by The Stig

I wanted to know how I can parse an IPv6 address in C and convert it to a 128 bit value?

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

So a hex address like 1:22:333:aaaa:b:c:d:eneeds to be converted to its 128 bit equivalent binary. The problem is the IP address could be of the type ::2and its variant since they are valid IPv6 address.

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

The input is from the keyboard and hence is in ASCII format.

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

回答by dreamlax

You can use POSIX inet_ptonto convert a string to a struct in6_addr.

您可以使用 POSIXinet_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?
}

回答by Thanatos

getaddrinfo()can understand IPv6 addresses. Pass AF_INET6 to it in the hints, as well as AI_NUMERICHOST (to prevent a DNS lookup). Linux has it, Windows has it as of Windows XP.

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

回答by Ales Teska

You can use getaddrinfo()POSIX function. It is more flexible than inet_pton(), for example it automatically detects IPv4 and IPv6 address formats, it can resolve even hostnames (using DNS resolving) and port/service names (using /etc/services).

您可以使用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);

The IPv6 address is stored in the struct sockaddr_storage resultvariable.

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
}

回答by YeenFei

To parse IPv6 in C, you need to build yourself a utility function, which tokenized string (colon for hex blocks, and forward-slash for subnet bits).

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

  1. Tokenize raw IPv6 string into smaller substring.
  2. Convert non-empty substring into hex blocks. (ASCII to decimal conversion)
  3. Expand hex block into 2-bytes by padding zero in front. (only leading zeroes get trimmed)
  4. Complete IPv6 should have 8 hex blocks, calculate missing hex-block(s). (zeroes grouping can happen only once)
  5. Reinsert missing hex-block. (use index of the empty substring)
  1. 将原始 IPv6 字符串标记为更小的子字符串。
  2. 将非空子字符串转换为十六进制块。(ASCII 到十进制转换)
  3. 通过在前面填充零将十六进制块扩展为 2 个字节。(只有前导零被修剪)
  4. 完整的 IPv6 应该有 8 个十六进制块,计算丢失的十六进制块。(零分组只能发生一次)
  5. 重新插入丢失的六角块。(使用空子串的索引)

回答by Fernando Gonzalez Sanchez

Rosetta has samples in several languages: https://rosettacode.org/wiki/Parse_an_IP_Address

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

回答by Patryk

if you can use boost, something like this should work:

如果你可以使用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;
}

It is a bit more portable than for example POSIX specific functions.

它比例如 POSIX 特定功能更便携。

回答by Ken Bloom

In Windows, you can use WSAStringToAddress, which is available since Windows 2000.

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