統計兩個IP地址之間的IP個數
問題
求兩個IP地址之間的IP個數,例如192.18.16.1~192.18.16.5,2001:DB8:0000:0023:0008:0800:200C:417C~2001:DB8:0:23:8:800:200C:417D之間的IP個數?
演算法
`
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class IPCount {
public long ipv4ToNumber(String ip) { long rs = 0; if (ip == null || ip.isEmpty()) { return rs; } String[] ips = ip.split("\\."); for (int i = 0; i < ips.length; i++) { rs += Integer.parseInt(ips[i]) * Math.pow(256, (3 - i)); } return rs; } /** * 數字轉換成IPv4地址 * @param number * @return */ public String numberToIpv4(long number) { String ip = ""; List<String> ips = new ArrayList<String>(); for (int i = 0; i < 8; i++) { ips.add(String.valueOf(number % 256)); number = number >> 8; } for (int i = ips.size() - 1; i >= 0; i--) { ip = ip.concat(ips.get(i)); if (i > 0) { ip = ip.concat("."); } } return ip; } /** * IPv6地址轉換成數字 * @param ip * @return */ public BigInteger ipv6ToNumber(String ip) { String[] ips = ip.split(":"); BigInteger rs = new BigInteger("0"); for (int i = 0; i < ips.length; i++) { BigInteger a = BigInteger.valueOf(Integer.parseInt(ips[i], 16)); BigInteger b = BigInteger.valueOf(65536).pow(7 - i); BigInteger c = a.multiply(b); rs = rs.add(c); } return rs; } /** * 數字轉換成IPV6地址 * @param number * @return */ public String numberToIpv6(BigInteger number) { String ip = ""; List<String> ips = new ArrayList<String>(); for (int i = 0; i < 8; i++) { ips.add(Integer.toHexString(number.divideAndRemainder(BigInteger.valueOf(65536))[1].intValue())); number = number.shiftRight(16); } for (int i = ips.size() - 1; i >= 0; i--) { ip = ip.concat(ips.get(i)); if (i > 0) { ip = ip.concat(":"); } } return ip; } /** * 查詢兩個IP地址之間的IP * @param startIp * @param endIp * @return */ public List<String> findIPs(String startIp, String endIp) { BigInteger startNumber = this.ipv6ToNumber(startIp); BigInteger endNumber = this.ipv6ToNumber(endIp).add(BigInteger.valueOf(1)); List<String> ips = new ArrayList<String>(); while (startNumber.compareTo(endNumber) < 0) { ips.add(this.numberToIpv6(startNumber)); startNumber = startNumber.add(BigInteger.valueOf(1)); } return ips; }
}
`
原理
無論是IPV4還是IPV6,它們其實都是對應整數值,但是為了方面人的理解和分析,對這個整數採用了某種格式化的方式進行表示,比如IPV4是一個32的整數,採用點分十進位制的格式表示,IPV6是一個128位的整數,採用冒分十六進位制的個數表示,也就是說對於一個給定的32位整數,可以轉換成一個IP地址,同樣,對於一個給定的IP地址,可以轉換成一個32位的整數,所以計算兩個IP地址之間的個數或者IP,其實就是計算兩個整數之間有多少個整數
只是IPV6對應一個128位的整數,所以使用Java基本的資料型別long是無法儲存這麼多位的資料的,需要採用了BigInteger