InetAddress.getAllByName() 仅接收具有 java.net.preferIPv6Addresses 的 IPv4 地址

InetAddress.getAllByName() only receives IPv4 addresses with java.net.preferIPv6Addresses

tl;博士

InetAddress.getAllByName() 仅接收 IPv4 地址列表,即使 java.net.preferIPv6Addresses 设置为 true,在 NAT64 网络上,在 iOS 设备上也是如此。相同的代码在连接到同一网络的 android 上按预期工作。

这意味着在纯 ipv6 网络中(根据 Apple 商店的要求)任何尝试建立 HttpURLConnection 的应用程序都将失败,并将被 Apple 拒绝。

原版Post

我正在 Java 中为 iOS 创建一个应用程序,我使用 HttpsURLConnection 连接到服务器并且一切正常,直到我在 NAT64 网络上进行测试。该应用程序被 Apple 审核团队拒绝,因此我正在使用 NAT64 网络在本地进行测试。

要创建我的 NAT64 网络,我遵循以下步骤:Supporting IPv6 DNS64/NAT64 Networks

示例代码:

HttpsURLConnection testConn = null;
try {
    URL testUrl = new URL("https://google.com");
    testConn = (HttpsURLConnection) testUrl.openConnection();
    testConn.connect();     
}catch (Exception e){
    e.printStackTrace();
}finally {
    if(testConn != null){
        testConn.disconnect();              
    }           
}

此代码在我的 NAT64 网络上失败并显示 java.net.SocketException: Network is unreachable

我试过更改系统属性:

System.setProperty("java.net.preferIPv4Stack", "false");
System.setProperty("java.net.preferIPv6Addresses", "true");

我也试过将网站设置为我们服务器以外的服务器(如 google.com 的测试代码所示)。我还使用 wireshark 嗅探了来自 wi-fi 连接的数据包,唯一的流量是 google.com 的 DNS 请求,它似乎没有失败。最后,我还尝试回到 HttpURLConnection 以防问题与 HTTPS 有关。

同样值得注意的是,测试中的 safari iPhone 可以毫无问题地连接到我们所有的服务器和域,并且该设备似乎具有稳定且功能正常的互联网连接。当连接到同一个 NAT64 网络时,该应用程序在我的 android 设备上也会失败。

编辑:

设置 System.setProperty("java.net.preferIPv6Addresses", "true"); 解决了 android 上的问题,所以现在问题被隔离到我的 iPhone5 在 NAT64 网络上。在这个阶段我最好的猜测是 属性 被另一个 class 设置并且被忽略了。我曾尝试在 class 顶部的静态初始化程序块中设置 属性,但无济于事。

编辑 2:

我在 iPhone5 上使用了 System.getProperty("java.net.preferIPv6Addresses") 并且它 returns true 所以它肯定被设置了,让我再次感到难过。

编辑 3:

我深入研究了 HttpsURLConnection,它实现了 PlainSocketImpl class 来处理它的连接,它使用 InetAddress。我决定测试一个 InetAddress,当我在 iPhone 上调用 InetAddress.getByName("google.com") 时,我得到一个 ipv4 地址,而在 android 上它是 returning 一个 ipv6地址。似乎 属性 java.net.preferIPv6Addresses 在 iOS 上被忽略了。我已尝试将 JDK 更新到最新版本,但这没有帮助。

我也刚试过 InetAddress.getAllByName("www.google.com"),它在 iPhone 上只有 return 个 IPv4 地址。我会说这显然是一个 DNS 问题,但为什么它在连接到同一网络的 android 上不是问题?

所以我现在知道问题出在哪里,但不知道如何解决。

解决方案是在最新版本的 MAF 上将我的应用程序升级到 运行。

详情:

即使我已将 Eclipse 和 MAF 更新到最新版本,我的应用程序仍在使用它的原始 MAF 版本作为目标 运行time。我通过查看我的目标 SDK 发现了这一点,并意识到我无法更改 运行时间版本。

要更新,我必须创建一个新项目,确保将目标 运行time 设置为最新版本的 MAF。然后我将我的代码迁移到这个新项目,并且能够在仅 IPv6 网络下成功 运行 我的应用程序。

(在撰写本文时,MAF 2.3.2 是 Eclipse 可用的最新版本)

如果没有创建新项目的方法,我找不到它。