2012-07-23 3 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)); 

하지만 내가 쓴 것은 매우 어리 석다. 나는 그것을 최적화하고 싶다. 누구도이 기능을 단순화하는 방법을 알고 있는가? 너무 많은 "for .... if ..."을 사용하지 마십시오.

답변

1

차단 된 서브넷을 마스크 + 기본 주소 쌍으로 표시하는 것이 좋습니다. . 11.22.33 들어

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

를 * 기본 주소는 마스크 0xffffff00 될 것입니다, 11*0x1000000 + 22*0x10000 + 33*0x100 될 것입니다 : 그래서 수표는 그렇게 볼 것이다.

단일 주소 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은 우리가 저장 될 것은 이전의 부분 ..actually * 포함 --those * 및

IpList2없이 IP의를 포함 말한다. *이 목록에. 예를 들어 202.121.189. *는 202.121.189로 저장됩니다 ..

따라서 주어진 IP 주소의 경우 IP 주소가 IpList1에 있는지 확인해야합니다. 그곳에 IP 주소가 없으면 각 IP에 대해 을 입력해야합니다. IPList 2 당신이 입력 IP의 하위 문자열인지 여부를 확인해야합니다.

따라서 for 및 if 루프가 필요하지 않습니다. (테스트되지 않은) 자바로 작성된

0

:

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 *** 코더임을 보여줄 것입니다.

관련 문제