如何在 Java 上同时支持 IPv4 和 IPv6

我们的Java程序之一在启动时,它只在IPv6上侦听(8080)

例如:

# netstat -ntpl

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::8080                 :::*                    LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               

问题是它无法从外部访问(本地主机除外),要解决此问题,我有这个手动添加

-Djava.net.preferIPv4Stack=true

但这使得该程序仅适用于IPv4网络。

是否可以像上面那样做一些类似sshd的事情,都支持IPv4和IPv6?


答案 1

我怀疑这与其说是Java编程问题,不如说是操作系统网络堆栈/ OS网络配置问题:

http://coding.derkeiler.com/Archive/Java/comp.lang.java.help/2009-09/msg00087.html

在某些操作系统上,单个本机 TCP 套接字可以同时侦听 IPv4 和 IPv6 上的端口。它能够接受来自远程 IPv4 和远程 IPv6 客户端的连接。在其他操作系统(如 WinXP)上,操作系统本机套接字无法执行此操作,但只能接受来自 IPv4 或 IPv6 的操作系统,而不能同时接受两者。在这些操作系统上,必须有两个侦听套接字才能接受来自远程 IPv4 和 IPv6 客户端的连接,一个套接字用于侦听 IPv4 连接,一个用于侦听 IPv6 连接。

Windows 7和Windows Server 2008处理双堆栈刚刚好;Windows XP与其说:)

您似乎在Linux上 - 大多数现代Linux桌面和服务器也可以毫无问题地处理双ipv4 ipv6。

这是一篇关于互操作性的好文章:

您知道如何为 Java 应用程序“关闭”IPV6:-Djava.net.preferIPv4Stack=true

您也可以强制服务器使用 IPV6,如下所示:echo 0 > /proc/sys/net/ipv6/bindv6only

这可以说是你最好的来源:

你绝对应该能够完成你想要的事情(至少在Java编程级别),除非你受到外部网络问题的限制:

Nodes)      V4 Only  V4/V6  V6 Only
            -------  -----  -------
V4 Only     x        x   
V4/V6       x        x      x
V6 Only              x      x

附言:

这是另一个很好的链接,它解释了套接字级别发生的情况。它不是Java(它是C),但恰恰适用示例原则:


答案 2

推荐