java - InetAddress.getAllByName() 只接收带有 java.net.preferIPv6Addresses 的 IPv4 地址

标签 java android ios ipv6 oracle-maf

tl;博士

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

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

原帖

我正在用 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 有关。

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

编辑:

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

编辑 2:

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

编辑 3:

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

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

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

最佳答案

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

详细信息:

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

noting the MAF runtime in the SDK settings

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

creating a new MAF project and setting the runtime version

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

如果有一种方法可以在不创建新项目的情况下做到这一点,我找不到它。

关于java - InetAddress.getAllByName() 只接收带有 java.net.preferIPv6Addresses 的 IPv4 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43336277/

相关文章:

java - 从另一个数组类调用方法

java - 我的生产者/消费者解决方案正确吗?

使用 Collections.sort 时 android.os.AsyncTask 中出现 java.lang.ArrayIndexOutOfBoundsException

java - 尝试修改 Activity 的后退按钮

java - MVVM 中是否允许操作?安卓

android - Kotlin Android - 从 fragment 复制到剪贴板

android - 如何测试演示者 MVP Android

ios - 使用 parse 为帖子点赞

ios - 需要为特定的 indexPath.row 设置新的约束

iphone - UILocalNotification 不会触发