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。我在这个阶段的最佳猜测是该属性由另一个类设置并被忽略。我已经尝试在我的班级顶部的静态初始化程序块中设置属性,但无济于事。
我使用System.getProperty("java.net.preferIPv6Addresses")
并在iPhone5上返回true
,因此它确实被设置了,让我再次难过。
我挖到了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上的问题?
所以我现在知道问题是什么,但不知道如何修复它。