所以我有~12600个子网:
例如.123.123.208.0/20
和IP.
我可以使用SQLite数据库或数组或其他任何东西
一个月前有一个类似的问题,但是我不是在寻找一个IP对一个子网而是一堆子网(显然是最有效的方式,希望不是O(总子网)):)
如何检查IP是否是其中一个子网中的一个,如果有助于优化,我需要true或false而不是子网.
当前列表中有类似的子网,例如:(实际提取)
123.123.48.0/22 <-- not a typo 123.123.48.0/24 <-- not a typo 123.123.90.0/24 123.123.91.0/24 123.123.217.0/24
总共它们的范围从4.xyz到222.xyz
最好的方法是IMO使用按位运算符.例如,123.123.48.0/22
表示(123<<24)+(123<<16)+(48<<8)+0
(= 2071670784;这可能是负数)作为32位数字IP地址,并且-1<<(32-22)
= -1024作为掩码.有了这个,同样,您的测试IP地址转换为数字,您可以这样做:
(inputIP & testMask) == testIP
例如,123.123.49.123在该范围内,2071671163 & -1024
2071670784也是如此
所以,这里有一些工具功能:
function IPnumber(IPaddress) { var ip = IPaddress.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); if(ip) { return (+ip[1]<<24) + (+ip[2]<<16) + (+ip[3]<<8) + (+ip[4]); } // else ... ? return null; } function IPmask(maskSize) { return -1<<(32-maskSize) }
测试:
(IPnumber('123.123.49.123') & IPmask('22')) == IPnumber('123.123.48.0')
收益率true
.
如果您的掩码采用"255.255.252.0"格式,那么您也可以使用IPnumber函数作为掩码.
试试这个:
var ip2long = function(ip){ var components; if(components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) { var iplong = 0; var power = 1; for(var i=4; i>=1; i-=1) { iplong += power * parseInt(components[i]); power *= 256; } return iplong; } else return -1; }; var inSubNet = function(ip, subnet) { var mask, base_ip, long_ip = ip2long(ip); if( (mask = subnet.match(/^(.*?)\/(\d{1,2})$/)) && ((base_ip=ip2long(mask[1])) >= 0) ) { var freedom = Math.pow(2, 32 - parseInt(mask[2])); return (long_ip > base_ip) && (long_ip < base_ip + freedom - 1); } else return false; };
用法:
inSubNet('192.30.252.63', '192.30.252.0/22') => true inSubNet('192.31.252.63', '192.30.252.0/22') => false