Ste*_*eve 16 javascript sql sqlite performance subnet
所以我有~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
Run Code Online (Sandbox Code Playgroud)
总共它们的范围从4.xyz到222.xyz
bar*_*art 23
最好的方法是IMO使用按位运算符.例如,123.123.48.0/22
表示(123<<24)+(123<<16)+(48<<8)+0
(= 2071670784;这可能是负数)作为32位数字IP地址,并且-1<<(32-22)
= -1024作为掩码.有了这个,同样,您的测试IP地址转换为数字,您可以这样做:
(inputIP & testMask) == testIP
Run Code Online (Sandbox Code Playgroud)
例如,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)
}
Run Code Online (Sandbox Code Playgroud)
测试:
(IPnumber('123.123.49.123') & IPmask('22')) == IPnumber('123.123.48.0')
Run Code Online (Sandbox Code Playgroud)
收益率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;
};
Run Code Online (Sandbox Code Playgroud)
用法:
inSubNet('192.30.252.63', '192.30.252.0/22') => true
inSubNet('192.31.252.63', '192.30.252.0/22') => false
Run Code Online (Sandbox Code Playgroud)
我设法通过使用节点网络掩码模块解决了这个问题。您可以通过执行以下操作来检查 IP 是否属于子网:
import { Netmask } from 'netmask'
const block = new Netmask('123.123.208.0/20')
const ip = '123.123.208.0'
console.log(block.contains(ip))
Run Code Online (Sandbox Code Playgroud)
将在这里打印true
。
您可以使用以下方法安装它:
npm i --save netmask
Run Code Online (Sandbox Code Playgroud)
将范围中的较低 ip 和较高 ip 转换为整数并将范围存储在数据库中,然后确保两列都已索引。
我的脑海中浮现出(伪代码):
function ipmap(w,x,y,z) {
return 16777216*w + 65536*x + 256*y + z;
}
var masks = array[ipmap(128,0,0,0), ipmap(196,0,0,0), ..., ipmap(255,255,255,255)]
function lowrange(w, x, y, z, rangelength) {
return ipmap(w, x, y, z) & masks[rangelength]
}
function hirange(w, x, y, z, rangelength) {
return lowrange(w, x, y, z, ,rangelength) + ipmap(255,255,255,255) - masks[rangelength];
}
Run Code Online (Sandbox Code Playgroud)
应该可以做到这一点。
要查找特定 ip 是否属于任何范围,请将其转换为整数并执行以下操作:
SELECT COUNT(*) FROM ipranges WHERE lowrange <= 1234567 AND 1234567 <= highrange
Run Code Online (Sandbox Code Playgroud)
查询优化器应该能够大大加快速度。
归档时间: |
|
查看次数: |
13630 次 |
最近记录: |