我正在使用 NsdManager 来解析本地网络(物联网设备)上的服务。 resolveService 返回一个带有主机和端口的 NsdServiceInfo。主机是一个具有链接本地地址(fe80::xxxx:xxxx:xxxx:9718)且未设置范围的Inet6Address对象。它还为 isLinkLocalAddress 返回一个 true。 如何在没有范围的情况下使用此链接本地地址进行任何网络调用?
我可以用我的本地机器 ping 服务的唯一方法是同时指定一个网络接口,例如像这样:
ping6 fe80::xxxx:xxxx:xxxx:9718%en0
.
感觉我在这里遗漏了 Android API 或 IPv6 规范的一些重要方面。 就个人而言,我宁愿只获得一个 IPv4 地址,但似乎也没有办法告诉 NsdManager。
首先,了解 IPv6 链路本地地址具有特定用途,通常不用于正常网络流量。
Link-Local 地址被设计用于寻址 用于自动地址配置等目的的单一链接, 邻居发现,或者没有路由器时。
接下来,由于设备中的所有接口都使用相同的本地链路网络,因此您必须使用区域 ID 来区分用于目标的接口。请记住,即使是主机(PC、打印机等)也有路由表,因此它们必须使用区域 ID 来区分链路本地地址。
来自 RFC 6874,在地址文字和统一资源标识符中表示 IPv6 区域标识符:
因为同一个非全球地址可能被多个 相同范围的区域(例如,使用链路本地地址 fe80::1 两个独立的物理链路)和一个节点可能有连接的接口 到相同范围的不同区域(例如,路由器通常有 连接到不同链路的多个接口),一个节点需要一个 internal 表示非全局地址属于哪个区域。 这是通过在节点内分配一个不同的“区域”来实现的 索引”到该节点所附加的相同范围的每个区域, 并通过允许地址的所有内部使用由 区域索引。
使用区域 ID 进行 IPv6 链路本地寻址是一项要求。事实上,链路本地寻址是目前唯一允许使用的区域 ID。
来自 RFC 6874,在地址文字和统一资源标识符中表示 IPv6 区域标识符:
为了限制这种风险,实现不得允许使用这种格式 除了明确定义的用法,例如发送到链接本地 前缀 fe80::/10 下的地址。在撰写本文时,这是 只有明确定义的用法是已知的。
您可以使用其他一些独特的寻址方式,例如ULA(RFC 4193,唯一本地 IPv6 单播地址),以避免该要求。对于 ULA,您可以在
fc00::/7
范围内使用寻址,但有限制将您限制在 fd00::/8
范围内,其中必须随机选择接下来的 40 位,给您一个 /48
前缀,您可以从中获得 65,536 个标准 /64
IPv6 网络。