2012-07-23 68 views
0

我想检查IP地址是否在一定范围内,仅匹配"*"。例如,“202.121.189.8”在“202.121.189。*”中。优化与IP范围相匹配的简单算术

的情况是,我有禁止的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; 
} 

测试代码:

string ip = "202.121.189.8"; 
List<string> ipList = new List<string>() { "202.121.168.25", "202.121.189.*" }; 

Console.WriteLine(IsInRange(ip, ipList)); 

但我认为我写的非常愚蠢,我想优化它,有没有人有一个想法如何简化这个功能?不要使用这么多的“......如果......”。

回答

1

一个好主意就是以一对的形式表示被禁止的子网:掩码+基地址。因此,您的支票将看起来像:

banned = (ip & mask == baseaddress & mask); 

对于33年11月22日*基址将11*0x1000000 + 22*0x10000 + 33*0x100,面膜会0xffffff00。

对于单个地址55.44.33.22,地址将是55*0x1000000 + 44*0x10000 * 33*0x100 + 22,掩码将为0xffffffff。

您需要将地址转换为32位int作为单独的过程。

之后,所有的,你的代码将看起来像:

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(); 
1

我认为你应该为IP保留一个单独的列表,并且*和那些没有任何标记的列表。

说IpList1包含IP的无* 和

IpList2 --those包含..actually *之前,我们将存储是一部分。*在该列表中。例如, 202.121.189。*将被存储为仅202.121.189 ..

因此,对于一个给定的IP addrerss你只需要您在IpList1该IP地址,如果没有找到它那边则 每个IP在IPList 2你需要检查它是否是输入IP的子字符串。

因此,没有复杂的要求,如果循环。

0

用Java编写的(未测试):

static boolean IsInRange(String ip, Vector<String> ipList) { 
    int indexOfStar = 0; 
    for (int i=0; i<ipList.size(); i++) { 
     if (ipList.contains("*")) { 
      indexOfStar = ipList.indexOf("*"); 
      if ((ip.substring(0, indexOfStar)).equals(ipList.get(i).substring(0, indexOfStar))) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 
0

我将在XKCD漫画使用空间填充曲线,如:http://xkcd.com/195/。它是函数H(x,y)=(H(x),H(y)),它将2维减小到1维。这也表明你是一个真正的B ***编码器。