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

Posted

技术标签:

【中文标题】如何在 Java 上同时支持 IPv4 和 IPv6【英文标题】:How to support both IPv4 & IPv6 on Java 【发布时间】:2012-05-09 20:16:50 【问题描述】:

我们的一个 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 编程问题,不如说是操作系统网络堆栈/操作系统网络配置问题:

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。

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

http://ntrg.cs.tcd.ie/undergrad/4ba2.02/ipv6/interop.html

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

您也可以像这样强制您的服务器使用 IPV6:echo 0 > /proc/sys/net/ipv6/bindv6only

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

http://docs.oracle.com/javase/6/docs/technotes/guides/net/ipv6_guide/index.html

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

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

PS:

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

Accept connections from both IPv6 and IPv4 clients

【讨论】:

以上是关于如何在 Java 上同时支持 IPv4 和 IPv6的主要内容,如果未能解决你的问题,请参考以下文章

域名如何优先解析ipv6

CentOS安装配置nginx-rtmp-module(同时支持IPv4和IPv6)

IPv6技术系列⑨——IPv6IPv4双栈实验

ubuntu服务器只有ipv6监听服务

IPv6改造方案:双栈技术

如何设计优雅的IP检查API以支持IPv4和IPv6