2013-07-26 14 views
12

Wie soll ich die Konvertierung von IPv6 zu long und umgekehrt durchführen?Konvertierung von IPv6 zu lang und von lang zu IPv6

Bisher habe ich:

public static long IPToLong(String addr) { 
      String[] addrArray = addr.split("\\."); 
      long num = 0; 
      for (int i = 0; i < addrArray.length; i++) { 
        int power = 3 - i; 

        num += ((Integer.parseInt(addrArray[i], 16) % 256 * Math.pow(256, power))); 
      } 
      return num; 
    } 

    public static String longToIP(long ip) { 
      return ((ip >> 24) & 0xFF) + "." 
        + ((ip >> 16) & 0xFF) + "." 
        + ((ip >> 8) & 0xFF) + "." 
        + (ip & 0xFF); 

    } 

Ist es richtig, Lösung oder ich etwas verpasst?

(Es wäre ideal, wenn die Lösung für die IPv4- und IPv6-arbeitet)

Adresse

Antwort

8

Eine IPv6 ist eine 128-Bit-Zahl, wie beschrieben here. Ein Long in Java wird auf 64 Bit dargestellt, daher benötigen Sie eine andere Struktur, wie zum Beispiel ein BigDecimal oder zwei Longs (ein Container mit einem Array aus zwei Longs oder einfach ein Array aus zwei Longs), um eine IPv6-Adresse zu speichern.

Unten ist ein Beispiel (nur Ihnen eine Vorstellung zu liefern):

public class Asd { 

public static long[] IPToLong(String addr) { 
    String[] addrArray = addr.split(":");//a IPv6 adress is of form 2607:f0d0:1002:0051:0000:0000:0000:0004 
    long[] num = new long[addrArray.length]; 

    for (int i=0; i<addrArray.length; i++) { 
     num[i] = Long.parseLong(addrArray[i], 16); 
    } 
    long long1 = num[0]; 
    for (int i=1;i<4;i++) { 
     long1 = (long1<<16) + num[i]; 
    } 
    long long2 = num[4]; 
    for (int i=5;i<8;i++) { 
     long2 = (long2<<16) + num[i]; 
    } 

    long[] longs = {long2, long1}; 
    return longs; 
} 


public static String longToIP(long[] ip) { 
    String ipString = ""; 
    for (long crtLong : ip) {//for every long: it should be two of them 

     for (int i=0; i<4; i++) {//we display in total 4 parts for every long 
      ipString = Long.toHexString(crtLong & 0xFFFF) + ":" + ipString; 
      crtLong = crtLong >> 16; 
     } 
    } 
    return ipString; 

} 

static public void main(String[] args) { 
    String ipString = "2607:f0d0:1002:0051:0000:0000:0000:0004"; 
    long[] asd = IPToLong(ipString); 

    System.out.println(longToIP(asd)); 
} 

}

+0

Ok, werde ich das tun. Was ist mit der Konvertierung? Ist es richtig gemacht? – Testeross

+0

Es ist ziemlich einfach, das zu testen: execute longToIP (IPToLong ("122.122.122.124")) und du wirst "34.34.34.36" statt der ursprünglichen "122.122.122.124" bekommen, was bedeutet, dass etwas nicht stimmt. –

+0

Sie haben Recht. Hast du eine Ahnung was falsch ist? – Testeross

6

Eine IPv6-Adresse in lange nicht gespeichert werden können. Sie können BigInteger statt lang verwenden.

public static BigInteger ipv6ToNumber(String addr) { 
    int startIndex=addr.indexOf("::"); 

    if(startIndex!=-1){ 


     String firstStr=addr.substring(0,startIndex); 
     String secondStr=addr.substring(startIndex+2, addr.length()); 


     BigInteger first=ipv6ToNumber(firstStr); 

     int x=countChar(addr, ':'); 

     first=first.shiftLeft(16*(7-x)).add(ipv6ToNumber(secondStr)); 

     return first; 
    } 


    String[] strArr = addr.split(":"); 

    BigInteger retValue = BigInteger.valueOf(0); 
    for (int i=0;i<strArr.length;i++) { 
     BigInteger bi=new BigInteger(strArr[i], 16); 
     retValue = retValue.shiftLeft(16).add(bi); 
    } 
    return retValue; 
} 


public static String numberToIPv6(BigInteger ipNumber) { 
    String ipString =""; 
    BigInteger a=new BigInteger("FFFF", 16); 

     for (int i=0; i<8; i++) { 
      ipString=ipNumber.and(a).toString(16)+":"+ipString; 

      ipNumber = ipNumber.shiftRight(16); 
     } 

    return ipString.substring(0, ipString.length()-1); 

} 

public static int countChar(String str, char reg){ 
    char[] ch=str.toCharArray(); 
    int count=0; 
    for(int i=0; i<ch.length; ++i){ 
     if(ch[i]==reg){ 
      if(ch[i+1]==reg){ 
       ++i; 
       continue; 
      } 
      ++count; 
     } 
    } 
    return count; 
} 
10

Sie auch java.net.InetAddress können
Es arbeitet mit IPv4- und IPv6 (alle Formate)

public static BigInteger ipToBigInteger(String addr) { 
    InetAddress a = InetAddress.getByName(addr) 
    byte[] bytes = a.getAddress() 
    return new BigInteger(1, bytes) 
} 
+2

Dadurch erhalten Sie negative Zahlen für die obere Hälfte des IP-Bereichs. Wenn Sie möchten, dass es nicht signiert ist, müssen Sie das Signum übergeben, damit es positiv bewertet wird (zB new BigInteger (1, Bytes)). – OTrain

+0

@OTrain Danke für den Kommentar. Antwort aktualisiert – Guigoz