2010-09-21 10 views
5

Vorrei sapere se esiste una libreria che posso utilizzare per convertire una rappresentazione di un indirizzo IPv6 lungo (come 2002: 9876: 57AB: 0000: 0000: 0000: 0000: 0001) nel modulo IPv6 compresso (in questo caso: 2002: 9876: 57AB :: 1).Libreria Java per la conversione di un indirizzo IPv6 lungo nella sua forma compressa

Non sono riuscito a trovare una tale libreria. Questa libreria non dovrebbe utilizzare alcun IP Api, non è necessario effettuare una connessione di rete.

già provato

return Inet6Address.getByName(longAdress).toString(); 

ma solo sostituisce i 4 zeri con 1 zero (in questo caso 2002: 9876: 57AB: 0: 0: 0: 0: 1).

qualche suggerimento?

+0

Vedi anche http://stackoverflow.com/q/7043983/21499 –

risposta

2
public class Ipv6AddressCompressor { 
    public static String getCompressedAddress(String longAddress) throws UnknownHostException { 
     longAddress = Inet6Address.getByName(longAddress).getHostAddress(); 
     return longAddress.replaceFirst("(^|:)(0+(:|$)){2,8}", "::"); 
    } 
} 

Questo dovrebbe proteggere contro indirizzi non validi (lancia l'UnknownHostException), e sarà correttamente comprimere finale indirizzi IPv4 (cioè 0: 0: 0: 0: 0: 0: 255.255.255.255 -> :: FFFF: FFFF). Questo proteggerà anche dagli indirizzi già compressi.

+2

Eccetto non rimuove zeri ridondanti, per esempio, ' 0000: 0000: 0001' dovrebbe essere ':: 1' ma diventa' :: 0001' - risolvibile facendo qualcosa come 'replaceAll (" (: | ^) 0 + (\\ d) "," $ 1 $ 2 ")' sul risultato, però. – gustafc

+0

Buona cattura. Il tuo \\ d dovrebbe essere [0-9A-Fa-F] però. Aggiornerà per risolvere. –

+0

Attenzione: Inet6Address.getByName può portare a query DNS se si alimenta ad es. un indirizzo danneggiato come ":: 1 ::" in esso. Questo può richiedere un paio di secondi per una singola chiamata! –

0

Puoi provare questo codice. Probabilmente funzionerà meglio rispetto all'equivalente regex (non che io abbia un benchmark o altro). È anche abbastanza ben collaudato.

Nota che è necessario utilizzare una rappresentazione numerica (in byte[]) dell'indirizzo IP. Per ottenerlo, è possibile eseguire InetAddress.getByName(ip).getAddress() se è necessario risolvere i nomi host o utilizzare la classe di utilità sun IPAddressUtil.textToNumericFormatV6(ip) per analizzare da un indirizzo IP senza risoluzione dell'host.

private static final char[] ipv6conseqZeroFiller = { ':', ':' }; 
private static final char ipv6hextetSeparator = ':'; 

/* 
* Convert numeric IPv6 to compressed format, where 
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::" 
*/ 
public static String ipv6toCompressedForm(byte[] src) { 
    assert src.length == 16; 
    //Find the longest sequence of 0's 
    int cmprHextet = -1; //start of compressed region (hextet index) 
    int cmprSize = 0; //length of compressed region 
    for (int hextet = 0; hextet < 8;) { 
     int curByte = hextet * 2; 
     int size = 0; 
     while (curByte < src.length && src[curByte] == 0 
       && src[curByte + 1] == 0) { 
      curByte += 2; 
      size++; 
     } 
     if (size > cmprSize) { 
      cmprHextet = hextet; 
      cmprSize = size; 
     } 
     hextet = (curByte/2) + 1; 
    } 
    if (cmprHextet == -1 || cmprSize < 2) { 
     //No compression can be applied 
     return ipv6toStr(src); 
    } 
    StringBuilder sb = new StringBuilder(39); 
    ipv6toStr(sb, src, 0, cmprHextet); 
    sb.append(ipv6conseqZeroFiller); 
    ipv6toStr(sb, src, cmprHextet + cmprSize, 8); 
    return sb.toString(); 
} 

/* 
* Convert numeric IPv6 to standard (non-compressed) format. 
* 
* Borrowed from Inet6Address.java #numericToTextFormat(byte[]) 
* Changed StringBuffer -> StringBuilder and ":" -> ':' for performance. 
*/ 
public static String ipv6toStr(byte[] src) { 
    assert src.length == 16; 
    StringBuilder sb = new StringBuilder(39); 
    ipv6toStr(sb, src, 0, 8); 
    return sb.toString(); 
} 

private static final void ipv6toStr(StringBuilder sb, byte[] src, 
     int fromHextet, int toHextet) { 
    for (int i = fromHextet; i < toHextet; i++) { 
     sb.append(Integer.toHexString(((src[i << 1] << 8) & 0xff00) 
       | (src[(i << 1) + 1] & 0xff))); 
     if (i < toHextet - 1) { 
      sb.append(ipv6hextetSeparator); 
     } 
    } 
} 
5

java-ipv6 è una libreria molto per questo. Gestisce bene anche gli intervalli di indirizzi.

1

The open-source IPAddress Java library può eseguire l'analisi degli indirizzi IP e produrre una varietà di stringhe. Disclaimer: sono il project manager di quella libreria.

codice

Esempio:

String ipv6 = "2002:9876:57AB:0000:0000:0000:0000:0001"; 
    try { 
     IPAddressString str = new IPAddressString(ipv6); 
     IPAddress addr = str.toAddress(); 
     String compressed = addr.toCompressedString(); 
     System.out.println(compressed); // 
    } catch(IPAddressStringException e) { 
     //e.getMessage has validation error 
    } 

uscita:

2002:9876:57ab::1 
Problemi correlati