Networking 确定何时尝试IPv6连接以及何时使用IPv4

Networking 确定何时尝试IPv6连接以及何时使用IPv4,networking,ipv6,Networking,Ipv6,我正在开发一个网络客户端程序,该程序连接到用户指定的公共服务器。如果用户给我一个同时具有IPv4和IPv6地址的主机名(通常是一个同时具有a和AAAA记录的DNS名称),我不确定应该如何决定连接哪个地址 问题是,机器支持IPv4和IPv6是很常见的,但只支持IPv4上的全局连接。最常见的情况是仅配置IPv6链路本地地址。目前,我能想到的最佳选择是: 首先尝试IPv6地址-如果连接失败,请尝试IPv4地址;或 只需让用户将其指定为配置设置(“首选ipv6”与“首选ipv4”) 我可以看到选项1的问

我正在开发一个网络客户端程序,该程序连接到用户指定的公共服务器。如果用户给我一个同时具有IPv4和IPv6地址的主机名(通常是一个同时具有
a
AAAA
记录的DNS名称),我不确定应该如何决定连接哪个地址

问题是,机器支持IPv4和IPv6是很常见的,但只支持IPv4上的全局连接。最常见的情况是仅配置IPv6链路本地地址。目前,我能想到的最佳选择是:

  • 首先尝试IPv6地址-如果连接失败,请尝试IPv4地址;或
  • 只需让用户将其指定为配置设置(“首选ipv6”与“首选ipv4”)
  • 我可以看到选项1的问题是,连接可能不会立即失败-可能需要很长时间才能超时。

    一些想法:

  • 允许用户根据每个站点指定首选项
  • 先试试IPv4
  • 在第一次连接时尝试并行IPv6
  • 在后续连接上,如果以前连接成功,请使用IPv6

  • 我说先试试IPv4,因为这是一个建立和测试得更好的协议。

    请试试IPv6。在绝大多数安装中,如果由于某种原因无法成功,尝试创建IPv6连接将立即失败:

    • 如果系统不支持IPv6套接字,则创建套接字将失败
    • 如果系统确实支持IPv6,并且配置了链路本地地址,则全局IPv6地址将不会有任何路由表条目。同样,本地内核将在不发送任何数据包的情况下报告失败
    • 如果系统确实具有全局IP地址,但缺少路由所需的某些链接,则源应收到ICMPv6错误消息,指示无法到达目的地;同样,如果目标具有IPv6地址,但服务未侦听该地址
    当然,在某些情况下可能会出现问题,例如,如果配置了全局(或隧道)地址,并且某些内容错误地过滤掉了ICMPv6错误消息。您不必担心这种情况——IPv4连接可能会以某种方式中断

    当然,您是否真的需要首先尝试IPv6地址仍有争议,您不妨第二次尝试。通常,您应该按照从getaddrinfo返回地址的顺序尝试地址。如今,系统支持配置选项,管理员可以通过这些选项决定从getaddrinfo返回地址的顺序。

    多亏了
    getaddrinfo()
    ,您应该让系统范围的配置来决定。就像Java一样。要求每一个应用程序尝试满足每一个可能的IPv6(mis)配置,这实际上是不可伸缩的!在配置错误的情况下,如果所有或所有应用程序都出现故障,用户会更加直观

    另一方面,您希望尝试大量记录恼人的延迟和超时,以便用户能够快速确定应该归咎于什么。理想情况下,就像其他延迟一样,包括(非常常见的)DNS超时。

    talk有解决方案。总结

    • 有时,DNS查找或随后与解析地址的连接会出现问题
    • 您不希望在连接到IPv4地址之前等待连接到IPv6地址超时,反之亦然
    • 您不希望等待AAAA记录的查找超时后再查找a记录,反之亦然
    • 您不希望在等待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演讲的幻灯片