2010-10-04 7 views
5

Ho un'applicazione Java che deve connettersi tramite socket a due server diversi su due macchine separate. Un server è stato configurato per l'ascolto sulle connessioni IPv4, mentre l'altro è stato configurato per l'ascolto sulle connessioni IPv6.Applicazione Java che desidera utilizzare contemporaneamente Inet4Address e Inet6Address

Ora, supponendo che "host1" sia il nome della macchina del server in ascolto sulle connessioni IPv4, mentre "host2" è il nome della macchina del server in ascolto sulle connessioni IPv6. Ho bisogno di ottenere un Inet4Address per "host1" e un Inet6Address per "host2" per creare una connessione socket a ciascun server, come ad esempio il seguente:

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

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

Tuttavia, la JVM di default preferisce utilizzare indirizzi IPv4 over Indirizzi IPv6 per motivi di compatibilità con le versioni precedenti. Quindi, nel codice precedente, il primo tentativo di connessione a "host1" ha esito positivo, ma il secondo tentativo di connessione a "host2" non riesce perché InetAddress.getByName("host2") restituisce un Inet4Address anziché Inet6Address.

ho capito che posso impostare la proprietà di sistema java.net.preferIPv6Addresses su true per preferire indirizzi IPv6 su IPv4, ma questo a sua volta fa sì che il secondo tentativo di connettersi a "host2" riesce, ma il primo tentativo di connettersi a "host1" fallito (!) perché InetAddress.getByName("host1") restituisce un Inet6Address anziché Inet4Address.

La proprietà di sistema java.net.preferIPv6Addresses viene letta solo una volta (vedere RigaInetAddress 212-218) e quindi non avrebbe alcun effetto anche se cambio il suo valore su falso dopo averlo impostato su true.

Quindi cosa posso fare in questo caso? Questo sembra un problema comune, quindi sicuramente deve esserci un modo per farlo.

Nota che posso ovviamente usare InetAddress.getByAddress() e fornire l'indirizzo IP di ogni macchina in modo esplicito, invece di tornare un Inet4Address e Inet6Address, ma io non voglio fare questo a meno che non devo proprio. Quindi altre soluzioni per favore.

Oh, sto usando java 1.6.0_19 nel caso in cui sia importante.

Grazie!

risposta

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

A meno che non si disponga di una specifica necessità per i metodi disponibili solo in Inet6Address o Inet4Address, non utilizzare queste classi direttamente, utilizzare invece InetAddress.

In questo modo non è necessario eseguire il cast e rischiare di avere un CCE.

Nel tuo caso non vedo davvero buoni motivi per utilizzare in modo specifico classi IPv6 o IPv4.

Ricorda, IPv6 è compatibile con IPv4, quindi non devi preoccuparti quando usi un indirizzo IPv4 con un sistema IPv6.


Risorse:

+2

Sì. Come ho detto, i due server stanno ascoltando rispettivamente le connessioni IPv4 e IPv6. Il casting che ho fatto nel codice di esempio sopra era solo per mostrare che volevo (e ho bisogno di) ottenere un 'Inet6Address' che poi devo passare a' InetSocketAddress' per connettermi a "host2" (il superamento di 'Inet4Address' causa un errore di connessione). Quindi, anche se uso sempre la "InetAddress" della superclasse, al di sotto di questo è in realtà "Inet4Address" o "Inet6Address", non è vero? E in questo caso, ho voluto rendere evidente il problema che sto avendo facendo esplicitamente il casting. – His

+0

Sì, rimarrà solo 'Inet4Address' o' Inet6Address' e qual è il problema? IPv6 è compatibile con IPv4 non dovrebbe esserci alcun problema. –

+0

Beh, non ne sono sicuro, perché non è quello che ho vissuto. Non riesco a usare un 'Inet6Address' (o' InetAddress' se vuoi) per connettermi al server in ascolto sulla connessione IPv4 - Ottengo un errore di connessione. Questo: 'nuovo InetSocketAddress (InetAddress.getByName (" host1 "), 7777)' con 'InetAddress.getByName (" host1 ")' la restituzione di Inet6Address/InetAddress, non funzionerà. Ma se 'InetAddress.getByName (" host1 ")' restituisce un 'Inet4Address/InetAddress', funzionerebbe. – His

0

Hai provato con Inet6Address.getAllByName("host2").

questo deve restituire l'indirizzo IPv6 dell'host, che può essere utilizzato per creare socket.

+1

'Inet6Address' non ha un'implementazione specifica di' getAllByName (String) ', quindi chiamare' Inet6Address.getAllByName (String) 'equivale a chiamare il metodo statico del genitore' InetAddress.getAllByName (String) '. – His

Problemi correlati