IPv4
网络中每一台主机和路由器的每一个端口都分配一个32比特的全球唯一的标识符,由网络号 + 主机号 两部分组成。为了表示方便,采用点分十进制法表示,即用四个字节表示一个IP地址,每个字节按照十进制表示为0~255,每个字节使用一个点分隔。
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | . | ...... | . | ...... | . | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
最小值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||||
最大值 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
如上图,如果将一个ip地址看作一个32位的整数的话,数据范围为:0 ~ 2^32 - 1 (无符号整数)。在java中,int占32位,但是最高位表示符号位,数据范围是不够的,所以在java中要使用一个整数类型表示所有的ip地址范围,不能使用int,所以选择long。
ipToLong
public static long ipToLong(String ip){
Long[] nums = Arrays.stream(ip.split("\\."))
.map(Long::parseLong).toArray(Long[]::new);
return (nums[0] << 24)
| (nums[1] << 16)
| (nums[2] << 8)
| nums[3];
}
longToIp
public static String longToIp(long ip){
long num4 = 0xFFL & ip; //取最后一个字节的数字
long num3 = 0xFFL & (ip >> 8); //移位之后取最后一个字节的数字
long num2 = 0xFFL & (ip >> 16);
long num1 = 0xFFL & (ip >> 24);
return new StringBuffer().append(num1).append(".")
.append(num2).append(".")
.append(num3).append(".")
.append(num4).toString();
}
子网掩码
将某个IP地址划分成网络地址和主机地址两部分。
public static long getMask(int maskBit){
//子网掩码也是32位,将0xFFFFFFFFL向右移动(32 - maskBit)位,在后面补 (32 - maskBit)个0
//然后再和0xFFFFFFFFL与一下,将高位移出的1消除掉
long mask = (0xFFFFFFFFL << (32 - maskBit)) & 0xFFFFFFFFL;
return mask;
}
public static String getMaskStr(int maskBit){
return longToIp(getMask(maskBit));
}
子网范围
public static long beginIpLong(String ip,int maskBit){
return ipToLong(ip) & getMask(maskBit);
}
public static String beginIp(String ip,int maskBit){
return longToIp(beginIpLong(ip,maskBit));
}
public static long endIpLong(String ip,int maskBit){
return beginIpLong(ip,maskBit)
+ (~getMask(maskBit)&0xFFFFFFFFL);
}
public static String endIp(String ip,int maskBit){
return longToIp(endIpLong(ip,maskBit));
}