InetAddress.getAllByName()仅使用java.net.preferIPv6Addresses接收IPv4地址

时间:2017-04-11 03:30:06

标签: java android ios ipv6 oracle-maf

TL;博士

InetAddress.getAllByName()仅在iOS设备上的NAT64网络上收到IPv4地址列表,即使java.net.preferIPv6Addresses设置为true。相同的代码在连接到同一网络的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有关。

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

编辑:

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

编辑2:

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

编辑3:

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

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

所以我现在知道问题是什么,但不知道如何修复它。

1 个答案:

答案 0 :(得分:1)

解决方案是升级我的应用程序以在最新版本的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的最新版本)

如果有办法在不创建新项目的情况下执行此操作,我无法发现它。