Networking 确定何时尝试IPv6连接以及何时使用IPv4
我正在开发一个网络客户端程序,该程序连接到用户指定的公共服务器。如果用户给我一个同时具有IPv4和IPv6地址的主机名(通常是一个同时具有Networking 确定何时尝试IPv6连接以及何时使用IPv4,networking,ipv6,Networking,Ipv6,我正在开发一个网络客户端程序,该程序连接到用户指定的公共服务器。如果用户给我一个同时具有IPv4和IPv6地址的主机名(通常是一个同时具有a和AAAA记录的DNS名称),我不确定应该如何决定连接哪个地址 问题是,机器支持IPv4和IPv6是很常见的,但只支持IPv4上的全局连接。最常见的情况是仅配置IPv6链路本地地址。目前,我能想到的最佳选择是: 首先尝试IPv6地址-如果连接失败,请尝试IPv4地址;或 只需让用户将其指定为配置设置(“首选ipv6”与“首选ipv4”) 我可以看到选项1的问
a
和AAAA
记录的DNS名称),我不确定应该如何决定连接哪个地址
问题是,机器支持IPv4和IPv6是很常见的,但只支持IPv4上的全局连接。最常见的情况是仅配置IPv6链路本地地址。目前,我能想到的最佳选择是:
我说先试试IPv4,因为这是一个建立和测试得更好的协议。请试试IPv6。在绝大多数安装中,如果由于某种原因无法成功,尝试创建IPv6连接将立即失败:
- 如果系统不支持IPv6套接字,则创建套接字将失败
- 如果系统确实支持IPv6,并且配置了链路本地地址,则全局IPv6地址将不会有任何路由表条目。同样,本地内核将在不发送任何数据包的情况下报告失败
- 如果系统确实具有全局IP地址,但缺少路由所需的某些链接,则源应收到ICMPv6错误消息,指示无法到达目的地;同样,如果目标具有IPv6地址,但服务未侦听该地址
getaddrinfo()
,您应该让系统范围的配置来决定。就像Java一样。要求每一个应用程序尝试满足每一个可能的IPv6(mis)配置,这实际上是不可伸缩的!在配置错误的情况下,如果所有或所有应用程序都出现故障,用户会更加直观
另一方面,您希望尝试大量记录恼人的延迟和超时,以便用户能够快速确定应该归咎于什么。理想情况下,就像其他延迟一样,包括(非常常见的)DNS超时。talk有解决方案。总结
- 有时,DNS查找或随后与解析地址的连接会出现问题
- 您不希望在连接到IPv4地址之前等待连接到IPv6地址超时,反之亦然
- 您不希望等待AAAA记录的查找超时后再查找a记录,反之亦然
- 您不希望在等待AAAA和A记录时暂停,然后再尝试连接最先返回的记录
实现这一点的最简单方法是允许网络API使用“按名称连接”网络API为您实现这一点。例如,在Java中:
InetSocketAddress socketAddress = new InetSocketAddress("www.example.com", 80);
SocketChannel channel = SocketChannel.open(socketAddress);
channel.write(buffer);
幻灯片说明在这一点上说:
这里,我们从主机创建一个不透明对象,称为InetSocketAddress
和端口,然后当我们打开插座通道时,就可以完成了
在掩护下,做任何必要的事情,没有
应用程序从未见过IP地址
Windows也有按名称连接的API。我没有用于的代码片段
那些在这里
现在,我并不是说这些API的所有实现都必须
现在就做正确的事情,但是如果应用程序正在使用这些API,
然后,随着时间的推移,实现可以得到改进
di!getaddrinfo()和类似API的区别在于
根本无法随着时间的推移而改善。API的定义是:
他们会给你一个完整的地址列表,所以他们必须等到
他们有完整的清单给你。getaddrinfo不可能
返回部分列表,然后再给您一些
在提出问题后,IETF提出了对该问题的答案,即a.k.a
相关的一点是,客户端和服务器可能都有IPv4和IPv6,但两者之间可能没有跳,因此不可能可靠地预测哪条路径会工作。使用IPv6而不是IPv4有什么好处?这确实是用户的一个问题-但如果他们不辞辛劳地加入公共IPv6 internet,我将假设他们有自己的理由。当我在试验(我只做了IPv4/IPv6部分,没有做SCTP)的原型代码时,“正确”的协议最终很快自动调谐。当然,在开始时会牺牲一些额外的流量。下面是关于这艘潜艇的IETF演讲的幻灯片