2010-10-04 23 views
5

J'ai une application Java qui doit se connecter via des sockets à deux serveurs différents sur deux machines distinctes. Un serveur a été configuré pour écouter les connexions IPv4, tandis que l'autre a été configuré pour écouter les connexions IPv6. Maintenant, en supposant que "host1" est le nom de l'ordinateur du serveur écoutant les connexions IPv4, alors que "host2" est le nom de l'ordinateur du serveur écoutant les connexions IPv6. Je dois obtenir un Inet4Address pour « host1 » et un Inet6Address pour « host2 » pour créer une connexion de socket pour chaque serveur, telles que les suivantes:Application Java souhaitant utiliser à la fois Inet4Address et Inet6Address en même temps

Inet4Address inet4 = (Inet4Address)InetAddress.getByName("host1"); 
InetSocketAddress soc4 = new InetSocketAddress(inet4, 7777); 
... 

Inet6Address inet6 = (Inet6Address)InetAddress.getByName("host2"); 
InetSocketAddress soc6 = new InetSocketAddress(inet6, 7777); 
... 

Cependant, la machine virtuelle Java par défaut préfère utiliser les adresses IPv4 sur Adresses IPv6 pour des raisons de compatibilité descendante. Ainsi, dans le code ci-dessus, la première tentative de connexion à "host1" réussit, mais la deuxième tentative de connexion à "host2" échoue car InetAddress.getByName("host2") renvoie un Inet4Address au lieu de Inet6Address. Je comprends que je peux définir la propriété système java.net.preferIPv6Addresses sur true pour préférer les adresses IPv6 sur IPv4, mais cela entraîne la réussite de la deuxième tentative de connexion à "host2", mais la première tentative de connexion à "host1" a échoué (!) car InetAddress.getByName("host1") renvoie Inet6Address au lieu de Inet4Address. La propriété système java.net.preferIPv6Addresses est lue une seule fois (voir InetAddress ligne 212-218) et n'a donc aucun effet même si je la ramène à false après l'avoir définie sur true.

Alors, que puis-je faire dans ce cas? Cela semble être un problème commun, alors il doit sûrement y avoir déjà un moyen de le faire.

Notez que je peux bien sûr utiliser InetAddress.getByAddress() et de fournir l'adresse IP de chaque machine explicitement au lieu de retourner un Inet4Address et Inet6Address, mais je ne veux pas le faire à moins d'avoir vraiment. Donc, d'autres solutions s'il vous plaît.

Oh, j'utilise java 1.6.0_19 au cas où cela serait important.

Merci!

Répondre

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); 
} 
0

Sauf si vous avez un besoin spécifique pour les méthodes uniquement disponibles dans Inet6Address ou Inet4Address, vous ne devez pas utiliser ces classes directement, utilisez plutôt InetAddress.

De cette façon, vous n'aurez pas besoin de lancer et risquez d'avoir un CCE.

Dans votre cas, je ne vois pas vraiment de bonnes raisons d'utiliser spécifiquement les classes IPv6 ou IPv4. Rappelez-vous, IPv6 est compatible avec IPv4, vous n'avez donc pas à vous inquiéter lorsque vous utilisez une adresse IPv4 avec un système IPv6.


Ressources:

+2

Je le fais. Comme je l'ai dit, les deux serveurs écoutent respectivement les connexions IPv4 et IPv6. Le casting que j'ai fait dans l'exemple ci-dessus était juste pour montrer que je voulais (et je dois) obtenir un 'Inet6Address' que j'ai ensuite besoin de passer à' InetSocketAddress' pour se connecter à "host2" (passer un 'Inet4Address' provoquer un échec de connexion). Donc, même si j'utilise tout le temps la superclasse 'InetAddress', en dessous il y a soit' Inet4Address' ou 'Inet6Address', n'est-ce pas? Et dans ce cas, je voulais rendre évident le problème que j'ai en faisant le casting explicitement. – His

+0

Oui, il restera toujours "Inet4Address" ou "Inet6Address", et quel est le problème? IPv6 est compatible avec IPv4 il ne devrait pas y avoir de problème. –

+0

Eh bien, je ne suis pas sûr, parce que ce n'est pas ce que j'ai vécu. Je ne peux pas utiliser un 'Inet6Address' (ou' InetAddress' si vous voulez) pour se connecter au serveur en écoutant la connexion IPv4 - j'obtiens un échec de connexion. Ceci: 'new InetSocketAddress (InetAddress.getByName (" host1 "), 7777)' avec 'InetAddress.getByName (" host1 ")' renvoyer une Inet6Address/InetAddress, ne fonctionnera pas. Mais si 'InetAddress.getByName (" host1 ")' renvoie un 'Inet4Address/InetAddress', cela fonctionnerait. – His

0

Avez-vous essayé avec Inet6Address.getAllByName("host2").

Ceci doit renvoyer les adresses IPv6 de l'hôte, qui peuvent être utilisées pour créer un socket.

+1

'Inet6Address' n'a pas d'implémentation spécifique de' getAllByName (String) ', donc appeler' Inet6Address.getAllByName (String) 'est vraiment le même que d'appeler la méthode statique du parent' InetAddress.getAllByName (String) '. – His