2013-07-26 31 views
12

Tôi nên thực hiện chuyển đổi từ IPv6 sang dài và ngược lại như thế nào?Chuyển đổi IPv6 thành dài và dài thành IPv6

Cho đến nay tôi có:

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

    } 

Có giải pháp đúng hay tôi bị mất cái gì?

(Nó sẽ là hoàn hảo nếu các giải pháp làm việc cho cả IPv4 và IPv6)

Trả lời

8

địa chỉ Một IPv6 là một con số 128-bit như mô tả here. Java dài được biểu diễn trên 64 bit, vì vậy bạn cần một cấu trúc khác, như BigDecimal hoặc hai longs (một vùng chứa có một dãy dài hai hoặc đơn giản là một mảng dài hai giây) để lưu trữ địa chỉ IPv6.

Dưới đây là một ví dụ (chỉ để cung cấp cho bạn một ý tưởng):

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, tôi sẽ làm điều đó. Điều gì về việc chuyển đổi? Nó có được thực hiện đúng không? – Testeross

+0

Rất dễ dàng để kiểm tra rằng: thực thi longToIP (IPToLong ("122.122.122.124")) và bạn sẽ nhận được "34.34.34.36" thay vì bản gốc "122.122.122.124" có nghĩa là một cái gì đó không chính xác. –

+0

Bạn nói đúng. Bạn có bất cứ ý tưởng gì là sai? – Testeross

6

địa chỉ Một IPv6 không thể được lưu trữ trong dài. Bạn có thể sử dụng BigInteger thay vì dài.

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

Bạn cũng có thể sử dụng java.net.InetAddress
Nó hoạt động với cả IPv4 và IPv6 (tất cả các định dạng)

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

Điều này sẽ cung cấp cho bạn số âm cho nửa trên của dải IP. Nếu bạn muốn nó được unsigned, bạn cần phải vượt qua trong signum để giữ cho nó tích cực có giá trị (tức là BigInteger mới (1, byte)). – OTrain

+0

@OTrain Cảm ơn bạn đã bình luận. Đã cập nhật phản hồi. – Guigoz

Các vấn đề liên quan