在实际的Java程序中使用IPv6 [英] Using IPv6 in a real-world Java program

查看:1169
本文介绍了在实际的Java程序中使用IPv6的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如今,IPv6的使用开始缓慢,因此我目前正在修复和更新所有要为IPv6准备的应用程序.

IPv6 usage is slowly starting nowadays, so I'm currently in the process of fixing and updating all applications to be prepared for IPv6.

应用程序之一是Java编辑器JOSM( http://josm.openstreetmap.de/) .即使操作系统使用IPv6,Java也不会在默认配置中真正使用IPv6.

One of the applications is the Java editor JOSM (http://josm.openstreetmap.de/). Java does not really use IPv6 in the default configuration even if the OS uses IPv6.

根据 http://docs.oracle.com/javase/1.5.0/docs/guide/net/ipv6_guide/#using 我将java.net.preferIPv6Addresses设置为true以使其使用IPv6.结果是有关网络连接中断的用户错误报告.

According to http://docs.oracle.com/javase/1.5.0/docs/guide/net/ipv6_guide/#using I set java.net.preferIPv6Addresses to true to let it use IPv6. Result have been user bug reports about broken internet connection.

似乎Java仅切换为使用IPv6地址而不是IPv4,但没有执行其他操作.我维护的所有基于C/C ++的软件都已更改为可以检查并尝试所有可用的IP地址,因此只要其中一个地址有效,就可以跳过损坏的IPv6(或IPv4)地址.对我来说,Java只能尝试一次,而在现实世界中是行不通的.

It seems Java only switches to use IPv6 address instead of IPv4, but does nothing else. All C/C++ based software I maintain has been changed to check and try all available IP addresses, so broken IPv6 (or IPv4) addresses are skipped as long as one of the addresses works. For me it looks like Java only tries once, which does not work in real world.

通常,当使用IPv6进行隧道传输时,操作系统通常更喜欢IPv4,而不是IPv6.看来Java确实也忽略了此设置.

Also usually the OS prefers IPv4 over IPv6, when IPv6 is tunneled. It seems like Java does ignore this settings as well.

所以我的问题是:有没有什么好的方法可以使Java应用程序默认情况下使用IPV6,而又不会破坏IPv4用户的应用程序.

So my question is: Are there any good ways to get a Java application to use IPV6 by default when available without breaking the application for IPv4 users.

用户错误报告: http://josm.openstreetmap.de/ticket/8562 http://josm.openstreetmap.de/ticket/8627 .

推荐答案

该主题似乎对其他人也很有趣,因此我将介绍当前的解决方案.

It seems that topic is interesting for others as well, so I describe my current solution.

  • 该软件会检测IPv6是否正常工作并记住状态->这是通过将TCP连接到已知IPv6地址(isReachable()的Ping不可靠,请参见此错误报告)来完成的: https://josm.openstreetmap.de/ticket/11452 ).
  • 基于记住的状态,软件将"java.net.preferIPv6Addresses"设置为"true".
  • 这意味着对于从IPv4到IPv6网络的切换,它将使用IPv4直到下一次重新启动为止.
  • 对于从启用了IPv6的网络到仅IPv4的网络的切换,它根本无法工作,而通过重新启动软件可以解决此问题.
  • 如有疑问,我们认为IPv6不起作用.
  • 进行检测后,无法更改"java.net.preferIPv6Addresses",因为该值似乎仅在第一个网络连接之前是只读的.如果有一种方法可以在运行时重置该状态,我想了解一下.
  • The software does an detection whether IPv6 works or not and remembers the state -> This is done by doing a TCP connect to a known IPv6 address (Ping of isReachable() is not reliable, see this bug report: https://josm.openstreetmap.de/ticket/11452).
  • Based on the remembered state the software starts with "java.net.preferIPv6Addresses" set to "true".
  • This means for a switch from IPv4 to a IPv6 network it will use IPv4 until next restart which is ok.
  • For a switch from an IPv6 enabled to an IPv4 only network it will not work at all which is solved by restarting the software.
  • In case of doubt we assume IPv6 does not work.
  • It is not possible to change "java.net.preferIPv6Addresses" after doing the detection, as that values seems to be read only before the first network connection. If there is a way to reset that state during runtime I'd like to know about it.

此解决方案似乎有效,日志ATM中大约有4%的IPv6连接,但这并不是一个令人满意的解决方案.

This solution seems to work, we have about 4% IPv6 connections in our logs ATM, but is is not really a satisfying solution.

/**
 * 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆