我有一个Java应用程序需要通过套接字连接到两台不同的机器上的两个不同的服务器。一台服务器已配置为侦听IPv4连接,而另一台服务器已配置为侦听IPv6连接。
现在,假设“host1”是侦听IPv4连接的服务器的计算机名称,而“host2”是侦听IPv6连接的服务器的计算机名称。我需要为“host1”获取Inet4Address
,为“host2”获取Inet6Address
以创建到每个服务器的套接字连接,例如:
Inet4Address inet4 = (Inet4Address)InetAddress.getByName("host1");
InetSocketAddress soc4 = new InetSocketAddress(inet4, 7777);
...
Inet6Address inet6 = (Inet6Address)InetAddress.getByName("host2");
InetSocketAddress soc6 = new InetSocketAddress(inet6, 7777);
...
但是,出于向后兼容性原因,默认情况下JVM更喜欢使用IPv6地址上的IPv4地址。因此,在上面的代码中,第一次尝试连接到“host1”成功,但第二次尝试连接到“host2”失败,因为InetAddress.getByName("host2")
返回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以防万一。
谢谢!
答案 0 :(得分:5)
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);
}
答案 1 :(得分:0)
除非您特别需要仅在Inet6Address
或Inet4Address
中使用的方法,否则您不应直接使用这些类,而应使用InetAddress
。
通过这种方式,您无需投射并冒险拥有CCE。
在您的情况下,我并没有真正理由使用特定的IPv6或IPv4类。
请记住,IPv6与IPv4兼容,因此在将IPv6地址与IPv6系统一起使用时,您不必担心。
资源:
答案 2 :(得分:0)
您是否尝试过Inet6Address.getAllByName("host2")
。
这必须返回主机的IPv6地址,可用于创建套接字。