一:背景:在生产中,我们会遇到根据ipv6的地址判断该ipv6属于哪个地市。
首先我们需要拿到全国的ipv6地址分配表。地址分配表一般是用掩码表示的。例如
2001:250:100::/40 中国 中国 * * 教育网 36.894402 104.166000 Asia/Chongqing UTC+8 * 86 CN AP
2001:250:200::/48 中国 北京 北京 清华大学网络科学与网络空间研究院 教育网 39.904989 116.405285 Asia/Shanghai UTC+8 110000 86 CN AP
2001:250:201::/48 中国 北京 北京 北京大学 教育网 39.904989 116.405285 Asia/Shanghai UTC+8 110000 86 CN AP
等,
如第一行 2001:250:100::/40 就表示 区段内的ip都属于中国 * * 教育网。
二:知识补充:ipv6有三种表示方法,具体可以百度去:
1.冒分十六进制表示法格式为X:X:X:X:X:X:X:X
2.0位压缩表示法,FF01:0:0:0:0:0:0:1101 → FF01::1101
3.内嵌IPv4地址表示法
为了实现IPv4-IPv6互通,IPv4地址会嵌入IPv6地址中,此时地址常表示为:X:X:X:X:X:X:d.d.d.d,前96b采用冒分十六进制表示,而最后32b地址则使用IPv4的点分十进制表示,例如::192.168.0.1与::FFFF:192.168.0.1
三:代码实现。下面的代码实现 输入一个ipv6掩码,输出代表的ipv6的开始地址,和结束地址。这样,拿到用户的ipv6具体地址后,就可以判断是否在开始,结束地址之中,从而判断所属地市。
public class IpV6Format {
private Map<String, String> hexToBinaryMap;
private Map<String, String> binaryToHexMap;
private String ipv6;
public IpV6Format() {
hexToBinaryMap = new HashMap<>();
hexToBinaryMap.put("0", "0000");
hexToBinaryMap.put("1", "0001");
hexToBinaryMap.put("2", "0010");
hexToBinaryMap.put("3", "0011");
hexToBinaryMap.put("4", "0100");
hexToBinaryMap.put("5", "0101");
hexToBinaryMap.put("6", "0110");
hexToBinaryMap.put("7", "0111");
hexToBinaryMap.put("8", "1000");
hexToBinaryMap.put("9", "1001");
hexToBinaryMap.put("a", "1010");
hexToBinaryMap.put("b", "1011");
hexToBinaryMap.put("c", "1100");
hexToBinaryMap.put("d", "1101");
hexToBinaryMap.put("e", "1110");
hexToBinaryMap.put("f", "1111");
binaryToHexMap = new HashMap<>();
binaryToHexMap.put("0000", "0");
binaryToHexMap.put("0001", "1");
binaryToHexMap.put("0010", "2");
binaryToHexMap.put("0011", "3");
binaryToHexMap.put("0100", "4");
binaryToHexMap.put("0101", "5");
binaryToHexMap.put("0110", "6");
binaryToHexMap.put("0111", "7");
binaryToHexMap.put("1000", "8");
binaryToHexMap.put("1001", "9");
binaryToHexMap.put("1010", "a");
binaryToHexMap.put("1011", "b");
binaryToHexMap.put("1100", "c");
binaryToHexMap.put("1101", "d");
binaryToHexMap.put("1110", "e");
binaryToHexMap.put("1111", "f");
}
private String hexToBinary(String hexString) {
hexString = hexString.toLowerCase();
StringBuilder binarySB = new StringBuilder();
if (hexString.length() == 0) {
hexString = "0000";
}
if (hexString.length() == 1) {
hexString = "000" + hexString;
}
if (hexString.length() == 2) {
hexString = "00" + hexString;
}
if (hexString.length() == 3) {
hexString = "0" + hexString;
}
for (char item : hexString.toCharArray()) {
binarySB.append(hexToBinaryMap.get(String.valueOf(item)));
}
return binarySB.toString();
}
public String[] formatIpV6(String ipv6String) {
String[] ret = new String[2];
StringBuilder sb = new StringBuilder();
ipv6="";
if (ipv6String.contains("/")) {
//如果带有掩码格式FE80::/64 , 1:123::ABCD:0:1/96
String groups[] = ipv6String.split("/");
ipv6 = groups[0];
int yanMa = Integer.valueOf(groups[1]);
String ipv6Items[] = ipv6.split(":");
long toInsertCount = 8 - Arrays.stream(ipv6Items).filter(p -> !p.equals("")).count();
fillIpv6(sb, ipv6Items, toInsertCount);
String yanMaString = sb.toString().substring(0, yanMa);
StringBuilder ipv6StartInBinary = new StringBuilder(yanMaString);
StringBuilder ipv6EndInBinary = new StringBuilder(yanMaString);
int fillCount = 128 - Integer.valueOf(yanMaString.length());
while (fillCount-- > 0) {
ipv6StartInBinary.append("0");
ipv6EndInBinary.append("1");
}
ret[0] = binaryToHexInIP(ipv6StartInBinary.toString());
ret[1] = binaryToHexInIP(ipv6EndInBinary.toString());
}
return ret;
}
private void fillIpv6(StringBuilder sb, String[] ipv6Items, long toInsertCount) {
for (String item : ipv6Items) {
if (!item.equals("")) {
sb.append(hexToBinary(item));
} else {
while (toInsertCount-- > 0) {
sb.append(hexToBinary(item));
}
}
}
while (toInsertCount-- > 0) {
sb.append(hexToBinary(""));
}
}
private String binaryToHexInIP(String ipInBinaryString) {
int ipLength = ipInBinaryString.length();
int index = 0;
int partCount = 0;
StringBuilder ret = new StringBuilder();
while (index < ipLength) {
String part = ipInBinaryString.substring(index, index + 4);
ret.append(binaryToHexMap.get(part));
partCount++;
if (partCount % 4 == 0 && partCount != 32) {
ret.append(":");
}
index += 4;
}
return ret.toString();
}
public static void main(String[] args) {
IpV6Format format = new IpV6Format();
// String[] ret1 = format.formatIpV6("2001:250:380B::/48");
// System.out.println("2001:250:380B::/48 range:" );
// System.out.println("start ip :" + ret1[0]);
// System.out.println("end ip :" + ret1[1]);
//
// String[] ret2 = format.formatIpV6("2001:256:800::/37");
// System.out.println("2001:256:800::/37 range:" );
// System.out.println("start ip :" + ret2[0]);
// System.out.println("end ip :" + ret2[1]);
String[] ret3 = format.formatIpV6("2001:256::/40");
System.out.println("2001:256::/40 range:");
System.out.println("start ip " + ret3[0]);
System.out.println("end ip " + ret3[1]);
// String[] ret4 = format.formatIpV6("::FFFF:192.168.0.1");
// System.out.println("::FFFF:192.168.0.1 range:" );
// System.out.println("start ip :" + ret4[0]);
// System.out.println("end ip :" + ret4[1]);
}
}
下面的代码实现了输入用户的ipv6地址输出标准冒分十六进制表示法,并且补足0。
public class UDFIPV6Format extends UDF {
private static Map<String, String> hexToBinaryMap;
private static Map<String, String> binaryToHexMap;
private static Map<Integer, String> binaryFillMap;
public UDFIPV6Format() {
hexToBinaryMap = new HashMap<>();
hexToBinaryMap.put("0", "0000");
hexToBinaryMap.put("1", "0001");
hexToBinaryMap.put("2", "0010");
hexToBinaryMap.put("3", "0011");
hexToBinaryMap.put("4", "0100");
hexToBinaryMap.put("5", "0101");
hexToBinaryMap.put("6", "0110");
hexToBinaryMap.put("7", "0111");
hexToBinaryMap.put("8", "1000");
hexToBinaryMap.put("9", "1001");
hexToBinaryMap.put("a", "1010");
hexToBinaryMap.put("b", "1011");
hexToBinaryMap.put("c", "1100");
hexToBinaryMap.put("d", "1101");
hexToBinaryMap.put("e", "1110");
hexToBinaryMap.put("f", "1111");
binaryToHexMap = new HashMap<>();
binaryToHexMap.put("0000", "0");
binaryToHexMap.put("0001", "1");
binaryToHexMap.put("0010", "2");
binaryToHexMap.put("0011", "3");
binaryToHexMap.put("0100", "4");
binaryToHexMap.put("0101", "5");
binaryToHexMap.put("0110", "6");
binaryToHexMap.put("0111", "7");
binaryToHexMap.put("1000", "8");
binaryToHexMap.put("1001", "9");
binaryToHexMap.put("1010", "a");
binaryToHexMap.put("1011", "b");
binaryToHexMap.put("1100", "c");
binaryToHexMap.put("1101", "d");
binaryToHexMap.put("1110", "e");
binaryToHexMap.put("1111", "f");
binaryFillMap = new HashMap<>();
binaryFillMap.put(1, "0");
binaryFillMap.put(2, "00");
binaryFillMap.put(3, "000");
binaryFillMap.put(4, "0000");
binaryFillMap.put(5, "00000");
binaryFillMap.put(6, "000000");
binaryFillMap.put(7, "0000000");
}
/**
* format ipv6 to standard format
*/
public String evaluate(Text n) {
if (n == null || n.toString().trim().equals("")) {
return null;
}
String ipv6String = n.toString();
StringBuilder sb = new StringBuilder();
if (ipv6String.contains(".")) {
//ipv4混合模式
String ipv6Items[] = ipv6String.split(":");
int notNullCount = 0;
for (String item : ipv6Items) {
if (!item.equals("")) {
notNullCount++;
}
}
int toInsertCount = 7 - notNullCount;
fillIpv6(sb, ipv6Items, toInsertCount);
} else {
String ipv6Items[] = ipv6String.split(":");
int notNullCount = 0;
for (String item : ipv6Items) {
if (!item.equals("")) {
notNullCount++;
}
}
int toInsertCount = 8 - notNullCount;
fillIpv6(sb, ipv6Items, toInsertCount);
}
String ipv6InHex = binaryToHexInIP(sb.toString());
return ipv6InHex;
}
private void fillIpv6(StringBuilder sb, String[] ipv6Items, long toInsertCount) {
for (String item : ipv6Items) {
if (!item.equals("")) {
if (item.contains(".")) {
for (String part : item.split("\\.")) {
sb.append(fillBinary(Integer.toBinaryString(Integer.valueOf(part))));
}
} else {
sb.append(hexToBinary(item));
}
} else {
while (toInsertCount-- > 0) {
sb.append(hexToBinary(item));
}
}
}
while (toInsertCount-- > 0) {
sb.append(hexToBinary(""));
}
}
private String fillBinary(String input) {
int count = 8 - input.length();
if (count > 1) {
return binaryFillMap.get(count) + input;
} else {
return input;
}
}
private String hexToBinary(String hexString) {
hexString = hexString.toLowerCase();
StringBuilder binarySB = new StringBuilder();
if (hexString.length() == 0) {
hexString = "0000";
}
if (hexString.length() == 1) {
hexString = "000" + hexString;
}
if (hexString.length() == 2) {
hexString = "00" + hexString;
}
if (hexString.length() == 3) {
hexString = "0" + hexString;
}
for (char item : hexString.toCharArray()) {
binarySB.append(hexToBinaryMap.get(String.valueOf(item)));
}
return binarySB.toString();
}
private String binaryToHexInIP(String ipInBinaryString) {
int ipLength = ipInBinaryString.length();
int index = 0;
int partCount = 0;
StringBuilder ret = new StringBuilder();
while (index < ipLength) {
String part = ipInBinaryString.substring(index, index + 4);
ret.append(binaryToHexMap.get(part));
partCount++;
if (partCount % 4 == 0 && partCount != 32) {
ret.append(":");
}
index += 4;
}
return ret.toString();
}
public static void main(String[] args) {
//BigInteger ret = StringToBigInt("2001:256:101:2001:256:101:2001:256");
//System.out.println(ret);
UDFIPV6Format format = new UDFIPV6Format();
String ret1 = format.evaluate(new Text("::192.168.0.1"));
String ret2 = format.evaluate(new Text("2001:DB8:0:23:8:800:200C:417A"));
String ret3 = format.evaluate(new Text("2001::800:200C:417A"));
System.out.println(ret1);
System.out.println(ret2);
System.out.println(ret3);
}
}