看来这个话题对其他人来说也很有趣,所以我描述了我目前的解决方案。
- 软件做一个检测的IPv6是否工作并记住状态 - >这是做一个TCP连接到已知的IPv6地址来实现(isReachable平安()是不可靠的,看到这个错误报告: https://josm.openstreetmap.de/ticket/11452)。
- 基于记忆状态,软件以“java.net.preferIPv6Addresses”设置为“true”开始。
- 这意味着从IPv4切换到IPv6网络时,它将使用IPv4,直到下次重新启动为止。
- 对于从支持IPv6的网络切换到仅支持IPv4的网络,根本无法通过重新启动软件解决。
- 如有疑问,我们假设IPv6不起作用。
- 检测后无法更改“java.net.preferIPv6Addresses”,因为这些值似乎只能在第一次网络连接之前读取。如果有在运行时重置该状态的方法,我想知道它。
这个解决方案似乎有效,我们在日志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();
}
}
Java对于完全有效的系统也是失败的,其中IPV6仅用于本地,因为这些系统使用IPv6,而系统本身知道它没有IPv6连接。你的建议根本没有帮助。首先,我无法修复我们用户的所有安装。其次,我不知道如何取代Java中完整的网络处理。我需要一个真实世界的解决方案,而不仅仅是学术上的兴趣。 – 2013-04-24 07:52:51
对不起。如果是其他语言,我可以给你大量的示例代码。不过,这是你应该走的方向。 – 2013-04-24 14:58:47
你误解了复杂性。这个软件没有一个地方可以访问网络。可能有数百个不同的职位,其中一些职位隐藏在Java系统的深处。因此,为了让您的建议成立,必须有可能立即替换整个网络连接处理。我认为这不是一件容易的事(但也许有人知道一种方式)。目前,我们遇到的问题是向正在发布的所有HTTP连接添加正确的用户代理(对于其中一些而言没有问题,但对所有人来说都很难)。 – 2013-04-24 15:11:24