先补充下计算掩码位数
示例1
255.255.255.0
换成二进制是11111111.11111111.11111111.00000000
也就是24位
记住一个公式 128 64 32 16 8 4 2 1
每一个对应二进制里的一位1,所有加起来正好255(二进制中所有的1加起来的值)。有几个1,就对应的加几个数字
示例2
255.255.255.240
这是几位的掩码呢
255对应的肯定是8咯,那么240呢?
算算 128+64+32+16=240
,总共用到了四组数字,那么二进制应该就是11110000
完整的二进制11111111.11111111.11111111.11110000
那么,就是28位的地址
示例3
27位的掩码,算出掩码是多少
先换成二进制就是 11111111.11111111.11111111.11100000
前面三组不用看了,3*8=24
,最后一组呢
三个1,那就是对应三组数字128+64+32=224
正确的掩码为255.255.255.224
方式一:CIDR (192.1.1.0/24)
$ip = "192.1.1.1"; // 目标ip
$cidr = "192.1.1.0/24";
[$subnet, $bits] = explode('/', $cidr);
$ip = ip2long($ip); // 将 IPV4 的字符串互联网协议转换成长整型数字
$subnet = ip2long($subnet);
$mask = -1 << (32 - $bits);
if (($ip & $mask) == ($subnet & $mask)) {
echo "匹配成功";
} else {
echo "匹配失败";
}
方式二:起始IP方式匹配
$ips = array('192.168.1.1-192.168.1.254','192.168.0.1-192.168.0.254','192.168.3.1-192.168.3.254','192.168.4.1-192.168.4.254');
foreach ($ips as $ip) {
list($start, $end) = explode('-', $ip);
//去除32位下负数
$start = sprintf("%u", ip2long($start));
$end = sprintf("%u",ip2long($end));
$newips[] = array($start, $end);
}
function my_sort($a, $b) {
if ($a[0] == $b[0])
return 0;
return ($a[0] < $b[0]) ? -1 : 1;
}
//从大到小排序,IP段较多时可以使用2分查找或多分。
usort($newips, 'my_sort');
$matchip = '192.168.1.22';
$matchip = sprintf("%u",ip2long($matchip));
foreach ($newips as $value) {
if ($matchip > $value[0] && $matchip < $value[1])
echo "匹配IP段:". long2ip($value[0]) . '-' . long2ip($value[1]) . "\n";
}
补充 - CIDR获取IP段起始IP地址
function cidrToRange($cidr) {
$range = array();
$cidr = explode('/', $cidr);
$range[0] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1]))));
$range[1] = long2ip((ip2long($cidr[0])) + pow(2, (32 - (int)$cidr[1])) - 2);
return $range;
}
var_dump(cidrToRange("192.168.1.1/24"));