gpt4 book ai didi

c++ - BSD 套接字 ip6 inet_pton 以及如何检索作用​​域 ID

转载 作者:太空宇宙 更新时间:2023-11-04 01:12:05 26 4
gpt4 key购买 nike

我目前正在研究 IPv6 类并使用 inet_pton 从字符串中检索 IP 的实际二进制表示,即:

    AdressV6::AdressV6(const String & _ip)
{
int result = inet_pton(AF_INET6, _ip.c_str(), &(m_nativeAdress));

if(result <= 0)
//throw...

//How can I retrieve the sope ID from that?
}

有通用的方法吗?您是否只是手动解析字符串并查找听起来不太可靠的“%”:(

谢谢!

我现在尝试了手动解析,这似乎可行。不过,如果有更好的方法,请告诉我:

        //retrieve scope ID
uint32 scopeId = 0;
size_t pos = _ip.find("%");
if(pos != String::npos)
{
String theId = _ip.substr(pos+1);
scopeId = atoi(theId.c_str());
}
m_scopeId = scopeId;

最佳答案

在 BSD 和基于 BSD 的系统(例如包括 MacOS X)上,范围 ID 作为第二个 16 位字嵌入到链接本地地址的地址本身中。请引用FreeBSD Handbook并搜索“8.1.1.3 Scope Index”(不带引号)。

因此假设 intf1 的作用域 ID 为 1,intf2 的作用域 ID 为 2,inet_pton() 将在这些平台上按如下方式转换字符串:

"fe80::1234%intf1" -> fe80:1::1234
"fe80::1234%intf2" -> fe80:2::1234
"fe80::1234" -> fe80::1234

最后一个地址只是没有作用域,因此不能真正用于发送数据。

请注意,这是非标准的; inet_pton() 在基于 Linux 或 Windows 的系统上无法正常工作。但是,我认为即使在基于 Linux 和 Windows 的系统上,inet_pton() 也允许在末尾使用范围 ID,不过它会简单地忽略它。

对于非链接本地地址,这个技巧当然不起作用,但这些地址通常没有作用域。它们可以有范围,但通常每个接口(interface)都有一个自己的、唯一的接口(interface) IPv6 地址,基于它的接口(interface)标识符(即使你使用 DHCPv6,在这种情况下它有一个由 DHCP 服务器分配的 DHCP 地址,以及自动生成的IPv6 接口(interface)地址,除非禁止自动生成)。

struct sockaddr_in6 结构有一个用于范围 ID 的字段,但定义该字段的 RFC (RFC 2553 - Section 3.3) 并没有真正详细说明如何解释该字段。它只说:

The mapping of sin6_scope_id to an interface or set of interfaces isleft to implementation and future specifications on the subject ofsite identifiers.

所以这个字段完全是特定于实现的。

如果你希望这个字段被正确填写,并且你的代码应该尽可能跨平台,你应该使用getaddrinfo():

struct addrinfo hints;
struct addrinfo * result;

memset(&hints, 0, sizeof(hints));
// AI_NUMERICHOST prevents usage of DNS servers,
// it tells getaddrinfo that the input string is a numeric IP address.
hints.flags = AI_NUMERICHOST;
if (getaddrinfo("fe80::1234%intf1", NULL, &hints, &result) == 0) {
// result->ai_addr claims to be a pointer to struct sockaddr,
// in fact it will be a pointer to a struct sockaddr_in6 in our case.
struct sockaddr_in6 * so = (struct sockaddr_in6 *)result->ai_addr;

// It will be prefilled like this:
//
// so->sin6_family ==> AF_INET6;
// so->sin6_port ==> 0
// so->sin6_flowinfo ==> 0
// so->sin6_addr ==> fe80::1234
// so->sin6_scope_id ==> "intf1" as scope ID

// Do something with that sockaddr,
// e.g. set a port number and connect a socket to that address.

freeaddrinfo(result);
}

一个额外的提示:如果您想将返回的 getaddrinfo() 用于服务器套接字(您想要在本地绑定(bind)然后调用 accept() 的套接字在它上面),你还应该设置被动标志:

hints.flags = AI_NUMERICHOST | AI_PASSIVE;

并不是说它在大多数情况下都会起作用,但这是使用 getaddrinfo() 的正确方法。

关于c++ - BSD 套接字 ip6 inet_pton 以及如何检索作用​​域 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10329908/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com