2013-07-26 4 views
12

Comment effectuer une conversion de IPv6 à long et vice versa?Conversion IPv6 à long et long à IPv6

Jusqu'à présent, j'ai:

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

    } 

est-il une solution correcte ou je manqué quelque chose?

(Ce serait parfait si la solution a fonctionné pour les deux et ipv6 ipv4)

Répondre

8

Une adresse IPv6 est un nombre de 128 bits comme décrit here. Une longueur en Java est représentée sur 64 bits, donc vous avez besoin d'une autre structure, comme un BigDecimal ou deux longs (un conteneur avec un tableau de deux longs ou simplement un tableau de deux longs) afin de stocker une adresse IPv6.

Voici un exemple (juste pour vous donner une idée):

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, je le ferai. Qu'en est-il de la conversion? Est-ce que c'est bien fait? – Testeross

+0

Il est assez facile de tester cela: exécuter longToIP (IPToLong ("122.122.122.124")) et vous obtiendrez "34.34.34.36" au lieu de l'original "122.122.122.124" ce qui signifie que quelque chose ne va pas. –

+0

Vous avez raison. Avez-vous une idée de ce qui ne va pas? – Testeross

6

Une adresse IPv6 ne peut pas être stocké dans longtemps. Vous pouvez utiliser BigInteger au lieu de longtemps.

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

Vous pouvez également utiliser java.net.InetAddress
Il fonctionne aussi bien avec ipv6 (et ipv4 tous les formats)

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

Cela vous donnera des nombres négatifs pour la moitié supérieure de la plage IP. Si vous voulez que ce soit non signé, vous devez passer le signum pour le garder positif (ie nouveau BigInteger (1, octets)). – OTrain

+0

@OTrain Merci pour le commentaire. Réponse mise à jour – Guigoz