Math 优化匹配IP范围的简单算法
我想检查IP地址是否在特定范围内,仅通过Math 优化匹配IP范围的简单算法,math,ip,Math,Ip,我想检查IP地址是否在特定范围内,仅通过“*”匹配。例如,“202.121.189.8”在“202.121.189.*”中 场景是我有一个被禁止IP的列表,其中一些包含“*”,因此我编写了一个函数,到目前为止效果良好: static bool IsInRange(string ip, List<string> ipList) { if (ipList.Contains(ip)) { return true; } var ipSets
“*”
匹配。例如,“202.121.189.8”在“202.121.189.*
”中
场景是我有一个被禁止IP的列表,其中一些包含“*”
,因此我编写了一个函数,到目前为止效果良好:
static bool IsInRange(string ip, List<string> ipList)
{
if (ipList.Contains(ip))
{
return true;
}
var ipSets = ip.Split('.');
foreach (var item in ipList)
{
var itemSets = item.Split('.');
for (int i = 0; i < 4; i++)
{
if (itemSets[i] == "*")
{
bool isMatch = true;
for (int j = 0; j < i; j++)
{
if (ipSets[i - j - 1] != itemSets[i - j - 1])
{
isMatch = false;
}
}
if (isMatch)
{
return true;
}
}
}
}
return false;
}
静态布尔IsInRange(字符串ip,列表ipList)
{
if(ipList.Contains(ip))
{
返回true;
}
var ipSets=ip.分割('.');
foreach(ipList中的变量项)
{
var itemSets=item.Split('.');
对于(int i=0;i<4;i++)
{
如果(项集[i]=“*”)
{
bool-isMatch=true;
对于(int j=0;j
测试代码:
string ip = "202.121.189.8";
List<string> ipList = new List<string>() { "202.121.168.25", "202.121.189.*" };
Console.WriteLine(IsInRange(ip, ipList));
string ip=“202.121.189.8”;
List ipList=新列表(){“202.121.168.25”,“202.121.189.*.”;
控制台写入线(IsInRange(ip,ipList));
但是我觉得我写的东西很愚蠢,我想优化它,有人知道如何简化这个函数吗?不要使用太多的“for…if…”。一个好主意是以一对的形式表示被禁止的子网:掩码+基址。因此,您的支票将如下所示:
banned = (ip & mask == baseaddress & mask);
int numip = ip2int(ip);
bool isIpBanned = banList.Any(item =>
numip & item.mask == item.baseaddress & item.mask);
对于11.22.33.*基址将是11*0x1000000+22*0x10000+33*0x100
,掩码将是0xFFFF00
对于单个地址55.44.33.22,地址将为55*0x1000000+44*0x10000*33*0x100+22
,掩码将为0xFFFFFF
您需要将地址转换为32位整数,这是一个单独的过程
在此之后,您的代码将如下所示:
banned = (ip & mask == baseaddress & mask);
int numip = ip2int(ip);
bool isIpBanned = banList.Any(item =>
numip & item.mask == item.baseaddress & item.mask);
顺便说一句,通过这种方式,您将能够在较小的子集上表示甚至禁止
int ip2int(string ip) // error checking omitted
{
var parts = ip.Split('.');
int result = 0;
foreach (var p in parts)
result = result * 0x100 + int.Parse(p);
}
class BanItem { public int baseaddres; public int mask; }
BanItem ip2banItem(string ip)
{
BanItem bi = new BanItem() { baseaddres = 0, mask = 0 };
var parts = ip.Split('.');
foreach (var p in parts)
{
bi.baseaddress *= 0x100;
bi.mask *= 0x100;
if (p != "*")
{
bi.mask += 0xff;
bi.baseaddress += int.Parse(p);
}
}
return bi;
}
banList = banIps.Select(ip2banItem).ToList();
我认为你应该为带*的IP和不带星号的IP保留一个单独的列表 假设IpList1包含不带* 及 IpList2——包含*。实际上,我们将存储的是此列表中*之前的部分。例如,对于202.121.189。*将仅存储为202.121.189 因此,对于一个给定的IP地址,您只需要在IpList1中检查该IP地址,如果在那里找不到该地址的话 对于IPList 2中的每个Ip,您需要检查它是否是输入Ip的子字符串 因此不需要复杂的for和if循环。用Java编写(未测试):
静态布尔值IsInRange(字符串ip,向量ipList){
int indexOfStar=0;
对于(int i=0;i我会使用一个空间填充曲线,如xkcd漫画中所示:。它是函数H(x,y)=(H(x),H(y)),它将2维压缩为1维。这也表明你是一个真正的b***编码器