现在IPv6的使用正在慢慢开始,所以我目前正在修复和更新所有准备用于IPv6的应用程序。
其中一个应用程序是Java编辑器JOSM(http://josm.openstreetmap.de/)。即使操作系统使用IPv6,Java也不会在默认配置中使用IPv6。
根据
http://docs.oracle.com/javase/1.5.0/docs/guide/net/ipv6_guide/#using
我将java.net.preferIPv6Addresses
设置为true
以使其使用IPv6。结果是关于互联网连接中断的用户错误报告。
似乎Java只切换到使用IPv6地址而不是IPv4,但不做其他事情。我维护的所有基于C / C ++的软件都已更改为检查并尝试所有可用的IP地址,因此只要其中一个地址有效,就会跳过损坏的IPv6(或IPv4)地址。对我来说,看起来Java只尝试一次,这在现实世界中不起作用。
当IPv6通过隧道传输时,通常操作系统更喜欢IPv4而不是IPv6。看起来Java也忽略了这个设置。
所以我的问题是:在没有破坏IPv4用户的应用程序的情况下,有没有什么好方法可以让Java应用程序默认使用IPV6。
用户错误报告:http://josm.openstreetmap.de/ticket/8562,http://josm.openstreetmap.de/ticket/8627。
答案 0 :(得分:0)
所以你有两个问题:
操作系统供应商提供具有损坏的默认IPv6配置的操作系统,和/或用户启用损坏的IPv6配置。
当它不起作用时,他们会错误地责怪你。
你可以在这里做两件事:
告知用户如何禁用不必要和破坏的IPv6过渡机制,如Teredo,ISATAP和6to4。有关这些的说明可在互联网上广泛获得。
如果某些操作系统供应商默认情况下不会启用此垃圾,那也不错,但这可能要求太多。
在您的应用程序中实现Happy Eyeballs(RFC 6555)。这就是现代Web浏览器解决这个问题的方法。
Happy Eyeballs指定了一种算法,即应用程序尝试在(几乎)同时通过IPv6和IPv4进行连接,如果IPv6在短时间内无法工作,则回退到IPv4连接。该试验的结果也被缓存了几分钟。
不幸的是,我不熟悉Java,为你提供特定的代码来绕过Oracle默认隐藏的所有有趣的东西,但它应该可行。
答案 1 :(得分:0)
似乎这个主题对其他人来说也很有趣,所以我描述了我目前的解决方案。
这个解决方案似乎有效,我们的日志ATM中有大约4%的IPv6连接,但实际上并不是一个令人满意的解决方案。
/**
* Check if IPv6 can be safely enabled and do so. Because this cannot be done after network activation,
* disabling or enabling IPV6 may only be done with next start.
*/
private static void checkIPv6() {
if ("auto".equals(Main.pref.get("prefer.ipv6", "auto"))) {
new Thread(new Runnable() { /* this may take some time (DNS, Connect) */
public void run() {
boolean hasv6 = false;
boolean wasv6 = Main.pref.getBoolean("validated.ipv6", false);
try {
/* Use the check result from last run of the software, as after the test, value
changes have no effect anymore */
if (wasv6) {
Utils.updateSystemProperty("java.net.preferIPv6Addresses", "true");
}
for (InetAddress a : InetAddress.getAllByName("josm.openstreetmap.de")) {
if (a instanceof Inet6Address) {
if (a.isReachable(1000)) {
/* be sure it REALLY works */
Socket s = new Socket();
s.connect(new InetSocketAddress(a, 80), 1000);
s.close();
Utils.updateSystemProperty("java.net.preferIPv6Addresses", "true");
if (!wasv6) {
Main.info(tr("Detected useable IPv6 network, prefering IPv6 over IPv4 after next restart."));
} else {
Main.info(tr("Detected useable IPv6 network, prefering IPv6 over IPv4."));
}
hasv6 = true;
}
break; /* we're done */
}
}
} catch (IOException | SecurityException e) {
if (Main.isDebugEnabled()) {
Main.debug("Exception while checking IPv6 connectivity: "+e);
}
}
if (wasv6 && !hasv6) {
Main.info(tr("Detected no useable IPv6 network, prefering IPv4 over IPv6 after next restart."));
Main.pref.put("validated.ipv6", hasv6); // be sure it is stored before the restart!
new RestartAction().actionPerformed(null);
}
Main.pref.put("validated.ipv6", hasv6);
}
}, "IPv6-checker").start();
}
}