His*_*His 6 java sockets ipv4 ipv6 inetaddress
我有一个Java应用程序需要通过套接字连接到两台不同的机器上的两个不同的服务器.一台服务器已配置为侦听IPv4连接,而另一台服务器已配置为侦听IPv6连接.
现在,假设"host1"是侦听IPv4连接的服务器的计算机名称,而"host2"是侦听IPv6连接的服务器的计算机名称.我需要Inet4Address为"host1"和Inet6Address"host2"创建一个到每个服务器的套接字连接,如下所示:
Inet4Address inet4 = (Inet4Address)InetAddress.getByName("host1");
InetSocketAddress soc4 = new InetSocketAddress(inet4, 7777);
...
Inet6Address inet6 = (Inet6Address)InetAddress.getByName("host2");
InetSocketAddress soc6 = new InetSocketAddress(inet6, 7777);
...
Run Code Online (Sandbox Code Playgroud)
但是,出于向后兼容性原因,默认情况下,JVM优先使用IPv6地址上的IPv4地址.因此,在上面的代码中,第一次尝试连接到"host1"成功,但第二次尝试连接到"host2"失败,因为InetAddress.getByName("host2")返回an Inet4Address而不是Inet6Address.
我知道我可以将系统属性设置java.net.preferIPv6Addresses为true以优先选择IPv4上的IPv6地址,但这反过来导致第二次尝试连接到"host2"成功,但第一次尝试连接到"host1"失败(!)因为InetAddress.getByName("host1")返回一个Inet6Address代替Inet4Address.
系统属性java.net.preferIPv6Addresses只被读取一次(参见InetAddress line 212-218),因此即使我将其值设置为true后将其值更改为false也不会产生任何影响.
那么在这种情况下我能做些什么呢?这似乎是一个普遍的问题,所以必须有一种方法可以做到这一点.
请注意,我当然可以使用InetAddress.getByAddress(),并提供每台机器的IP地址,而不是明确要回的Inet4Address和Inet6Address,但我并不想这样做,除非我真的要.请其他解决方案.
哦,我正在使用java 1.6.0_19以防万一.
谢谢!
static Inet6Address getInet6AddressByName(String host) throws UnknownHostException, SecurityException
{
for(InetAddress addr : InetAddress.getAllByName(host))
{
if(addr instanceof Inet6Address)
return (Inet6Address)addr;
}
throw new UnknownHostException("No IPv6 address found for " + host);
}
Run Code Online (Sandbox Code Playgroud)