2010-10-04 16 views
5

Mam aplikację Java, która musi łączyć się przez gniazda do dwóch różnych serwerów na dwóch oddzielnych komputerach. Jeden serwer został skonfigurowany do nasłuchu na połączeniach IPv4, podczas gdy drugi został skonfigurowany do nasłuchu na połączeniach IPv6.Aplikacja Java, która chce używać zarówno Inet4Address, jak i Inet6Address w tym samym czasie.

Zakładając, że "host1" to nazwa urządzenia serwera nasłuchującego na połączeniach IPv4, a "host2" to nazwa urządzenia serwera nasłuchującego na połączeniach IPv6. Muszę dostać Inet4Address dla „host1” i Inet6Address dla „host2”, aby utworzyć połączenie z gniazdem do każdego serwera, takich jak:

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

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

jednak JVM domyślnie woli używać adresów IPv4 na Adresy IPv6 ze względu na kompatybilność wsteczną. Tak więc, w powyższym kodzie pierwsza próba połączenia z "host1" się powiedzie, ale druga próba połączenia z "host2" nie powiedzie się, ponieważ InetAddress.getByName("host2") zwraca Inet4Address zamiast Inet6Address.

Rozumiem, że mogę ustawić właściwość systemu na true, aby preferować adresy IPv6 przez IPv4, ale to z kolei powoduje, że druga próba połączenia z "host2" się powiedzie, ale pierwsza próba połączenia z "host1" nie powiodła się (!) ponieważ InetAddress.getByName("host1") zwraca wartość Inet6Address zamiast Inet4Address.

Właściwość systemowa jest tylko odczytywana tylko raz (patrz wiersz InetAddress 212-218), więc nie będzie miała żadnych efektów, nawet jeśli zmienię jej wartość na wartość false po ustawieniu na wartość true.

Co mogę zrobić w tym przypadku? Wydaje się, że jest to powszechny problem, więc na pewno musi istnieć sposób, aby to zrobić.

Zauważ, że mogę oczywiście użyć i podać adres IP każdego komputera jawnie zamiast tego, aby otrzymać ponownie Inet4Address i Inet6Address, ale nie chcę tego robić, chyba że naprawdę muszę. Więc proszę o inne rozwiązania.

Och, używam języka Java 1.6.0_19 na wszelki wypadek.

Dzięki!

Odpowiedz

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

Jeśli nie masz szczególnych wymagań dotyczących metod dostępnych tylko w Inet6Address lub Inet4Address, nie powinieneś używać tych klas bezpośrednio, zamiast tego użyj InetAddress.

W ten sposób nie trzeba rzucać i ryzykować posiadanie CCE.

W twoim przypadku naprawdę nie widzę dobrych powodów, aby używać konkretnych klas IPv6 lub IPv4.

Pamiętaj, że IPv6 jest zgodny z IPv4, więc nie musisz się martwić, gdy używasz adresu IPv4 w systemie IPv6.


Zasoby:

+2

Ja. Jak już powiedziałem, dwa serwery nasłuchują odpowiednio połączeń IPv4 i IPv6. Oddanie, które zrobiłem w powyższym przykładowym kodzie, miało pokazać, że chciałem (i muszę) uzyskać 'Inet6Address', który następnie muszę przekazać do' InetSocketAddress', aby połączyć się z "host2" (przekazanie 'Inet4Address' spowoduje spowodować błąd połączenia). Tak więc, mimo że używam tylko nadklasy 'InetAddress' przez cały czas, pod spodem jest to albo' Inet4Address' albo 'Inet6Address', czyż nie? I w tym przypadku chciałem, aby oczywiste było, że mam problem, wykonując casting jawnie. – His

+0

Tak, nadal będzie to tylko 'Inet4Address' lub' Inet6Address' i jaki będzie to problem? IPv6 jest kompatybilny z IPv4, więc nie powinno być problemu. –

+0

Cóż, nie jestem pewien, ponieważ tego nie doświadczyłem. Nie mogę użyć 'Inet6Address' (lub' InetAddress', jeśli chcesz) do połączenia się z serwerem nasłuchującym na połączeniu IPv4 - dostaję błąd połączenia. To: 'new InetSocketAddress (InetAddress.getByName (" host1 "), 7777)' z 'InetAddress.getByName (" host1 ")' zwracając adres Inet6Address/InetAddress, nie będzie działać. Ale jeśli 'InetAddress.getByName (" host1 ")' zwraca 'Inet4Address/InetAddress', to by działało. – His

0

Próbowałeś z Inet6Address.getAllByName("host2").

to musi zwrócić adres IPv6 hosta, którego można użyć do utworzenia gniazda.

+1

'Inet6Address' nie ma konkretnej implementacji' getAllByName (String) ', więc wywołanie' Inet6Address.getAllByName (String) 'jest naprawdę takie samo jak wywołanie statycznej metody rodzica' InetAddress.getAllByName (String) '. – His

Powiązane problemy