4

我有一个struct sockaddr包含 IPv4 映射 IPv6 地址的结构,例如::ffff:10.0.0.1. 我只想10.0.0.1在 C 编程语言的字符串(在本例中为 )中获取它的 IPv4 版本。我该如何去实现它?

4

3 回答 3

3

由于您的结构包含 IPV6 地址,我假设您有一个指向结构的struct sockaddr *指针(让我们命名它addrPtrstruct sockaddr_in6

您可以轻松获取地址字节。

const uint8_t *bytes = ((const struct sockaddr_in6 *)addrPtr)->sin6_addr.s6_addr;

然后将 12 添加到指针,因为前 12 个字节不感兴趣(10 0x00,然后 2 0xff)。只有最后 4 个重要。

bytes += 12;

现在,我们可以使用这四个字节来做任何我们想做的事情。例如,我们可能会将它们存储到 IPv4struct in_addr地址中。

struct in_addr addr = { *(const in_addr_t *)bytes };

然后我们可以使用inet_ntop(declared in <arpa/inet.h>) 得到一个字符串。

char buffer[16]; // 16 characters at max: "xxx.xxx.xxx.xxx" + NULL terminator
const char *string = inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
于 2012-06-27T19:36:48.617 回答
1

如果您想与其他类型的地址兼容,请使用 getnameinfo。

char hostbuf[NI_MAXHOST];
char *host;

if (getnameinfo(addr, addrlen, hostbuf, sizeof(hostbuf), NULL, 0, NI_NUMERICHOST))
    ;//error

if (strncmp(hostbuf, "::ffff:", sizeof("::ffff:") - 1) == 0)
    host = hostbuf + sizeof("::ffff:") - 1;
else
    host = hostbuf;
于 2012-06-27T21:52:29.347 回答
0

一旦您识别出 IPv4 映射地址,IPv4 部分就是地址的最低有效四个字节。我相信这可以通过以下方式完成:

struct sockaddr *address;  // this is the address
struct sockaddr_in6 *addrv6 = (struct sockaddr_in6 *)address;
unsigned long address;
memcpy(&address, addrv6->sin6_addr.s6_addr + 11, 4);

该文档指出该地址以网络顺序出现(最高有效字节在前)。如果这与您的机器架构不同,您需要调用 htonl() 以反转字节顺序。

于 2012-06-27T19:41:35.787 回答