2013-07-26 7 views
12

IPv6からlongへの変換とその逆の変換はどのように行うべきですか?変換IPv6からIPv6への長短の翻訳

は、これまでのところ私が持っている:

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

    } 

それが正解ですか私は何かを逃しましたか?

(溶液は、IPv4とIPv6の両方のために働いた場合、それは完璧であろう)

答えて

8

アンIPv6アドレスが記載hereとして128ビットの数値です。長いJavaは64ビットで表現されるので、IPv6アドレスを格納するために、BigDecimalや2つのlong(2つのlongの配列を持つコンテナ、あるいは2つのlongの配列)という別の構造が必要です。

以下

が(ちょうどあなたのアイデアを提供する)の例である:

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]をIPv4とIPv6の両方で動作しますjava.net.InetAddress
を使用することができ、私はそれを行います。変換はどうですか?それは正しいのでしょうか? – Testeross

+0

これをテストするのは簡単です:longToIP(IPToLong( "122.122.122.124"))を実行すると、元の "122.122.122.124"の代わりに "34.34.34.36"が得られます。 –

+0

あなたは正しいです。あなたは何が間違っているか考えていますか? – Testeross

6

IPv6アドレスが長いに保存することができません。 BigIntegerはlongの代わりに使用できます。

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

ます。また、それは(すべての形式)

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

これは、IP範囲の上半分に負の数を与えます。符号なしにするには、正の値を保持するためにsignumを渡す必要があります(つまり、新しいBigInteger(1、bytes))。 – OTrain

+0

@OTrainコメントありがとうございました。応答が更新されました。 – Guigoz