문제

서버 앱의 경우 IP 주소가 블랙리스트에 있는지 확인해야합니다.

IP 주소를 비교하는 가장 효율적인 방법은 무엇입니까? IP 주소를 정수로 변환하고 효율적으로 비교할 수 있습니까?

도움이 되었습니까?

해결책

사용중인 언어에 따라 다르지만 IP 주소는 일반적으로 네트워크 계층에서 32 비트 서명되지 않은 정수로 저장되므로 비교가 매우 빠릅니다. 그렇지 않더라도 고성능 패킷 스위칭 애플리케이션을 설계하지 않는 한 성능 병목 현상이 아닙니다. 조기 최적화를 피하십시오 - 테스트 가능성 및 확장 성을위한 프로그램을 설계하고 성능 문제가있는 경우 프로파일 러를 사용하여 병목 현상이 어디에 있는지 확인할 수 있습니다.

편집 : 명확히하기 위해 IPv4 주소는 32 비트 정수와 Netmask (IP 주소 비교에는 필요하지 않음)로 저장됩니다. 새롭고 현재 더 드문 IPv6을 사용하는 경우 주소는 128 비트 길이입니다.

다른 팁

32 비트 정수는 128 비트 IPv6 주소를 다루기 시작할 때까지 갈 길입니다.

텍스트 문자열로 비교하거나 int로 int로 변환하고 int로 비교해야한다면?

그것은 일반적으로 이런 종류의 조회에서 병목 현상이 아닙니다. 두 가지 방법을 모두 구현하고 어느 방법이 더 빨리 실행되는지 확인할 수 있습니다.

IP 주소 조회의 실제 문제는 일반적으로 효율적인 쿼리를 만드는 것입니다. 임의의 숫자뿐만 아니라 IP 주소를 다루고 있다는 사실을 활용하는 것입니다. 이를 달성하기 위해 조회 할 수 있습니다 LC 트리 그리고 아마도 이 기사

분명히 이것은 블랙리스트에 수만 또는 수백만 개의 출품작이있는 경우에만 관심을 가져야합니다. 10-20 개의 항목 만있는 경우 선형 검색이 선호되어야하며 실제로 더 흥미로운 질문은 텍스트 비교 대 정수 비교입니다.

static public bool IsEqual(string ToCompare,
                                      string CompareAgainst)
  {

     return IPAddressToLongBackwards(ToCompare)==IPAddressToLongBackwards(CompareAgainst);
  }

static private uint IPAddressToLongBackwards(string IPAddr)
  {
     System.Net.IPAddress oIP=System.Net.IPAddress.Parse(IPAddr);
     byte[] byteIP=oIP.GetAddressBytes();


     uint ip=(uint)byteIP[0]<<24;
     ip+=(uint)byteIP[1]<<16;
     ip+=(uint)byteIP[2]<<8;
     ip+=(uint)byteIP[3];

     return ip;
  }

내가 당신을 올바르게 이해한다면, 이것은 두 개의 IP 주소를 비교하는 코드입니다. 넌 이걸 원해? 당신은 다음과 같은 것들을 더 할 수 있습니다.

static public bool IsGreater(string ToCompare,
                               string CompareAgainst)
  {

     return IPAddressToLongBackwards(ToCompare)>
        IPAddressToLongBackwards(CompareAgainst);
  }

주소 바이트를 얻었 기 때문에.

그렇습니다. 효율적이기 위해서는 오래 걸릴 것이며 물론 정수 형태로 블랙리스트 IP를 색인해야합니다.

드라이버 레벨에서 TCP/IP 연결을 블랙리스트의 IP로 IPS로 분해하는 Peerguardian과 같은 도구를 사용하십시오. 매우 안전하고 코드가 필요하지 않습니다 (논란의 여지가 없습니다. 왜냐하면 코드가 필요하지 않음).

이 작업을 수행했는데 서명되지 않은 int (32 비트)를 사용하여 테스트했습니다. 가장 빠릅니다. 문자열 표현과 비교한다고 가정합니다.

당신을 도울 수있는 또 다른 것은 테이블을 만들 때, 과거에는 2 개의 colums를 가지고있었습니다 : Lowip and Highip; 그렇게하면 1 레코드 항목이있는 IP의 전체 범위를 블랙리스트 할 수 있었으며 범위에서 IP를 확인하여 여전히 우수한 성능을 얻을 수있었습니다.

나는 한때 누군가가 코드를 물려 받았다 생각 IP 주소를 4 INT로 저장하는 것은 모든 시간을 Int 's로 전환하는 데 소비하는 것을 제외하고는 정말 좋은 일이었습니다.

데이터베이스에서 문자열로 유지하는 것이 훨씬 쉬웠으며 단일 색인 만 필요했습니다. SQL Server가 4 개의 정수 열이 아니라 문자열을 얼마나 잘 색인화 할 수 있는지 놀랄 것입니다. 그러나이 IP 목록은 블랙리스트를위한 것이 아닙니다. 데이터베이스 왕복은 비용이 많이 듭니다.

데이터베이스가 과잉 인 경우 메모리 사전에 저장하지만 비교해야 할 사람이 얼마나 필요한지 모르기 때문에 추측입니다. 대부분의 해시 코드는 32 비트 INT이고 IPv4 주소는 32 비트이므로 IP 주소 자체는 좋은 해시 코드 일 수 있습니다.

그러나 다른 사람들이 지적한 바와 같이, 가장 좋은 옵션은 서버의 부하를 줄이고 특수 하드웨어를 구매하는 것입니다. 어쩌면 최근에 블랙리스트 IP를 메모리에 보관하고 주기적으로 새로운 것을 라우터에 게시합니다.

라우터 내부에서 소프트웨어를 만들려고하는 사람이라면 데이터 구조 책을 낚시하고 B- 트리와 같은 것을 만들어야합니다.

Radix 또는 Patricia Trie는 이에 대한 최적의 구조입니다.

Flow-Tools의 C 소스를 확인하십시오.http://www.splintered.net/sw/flow-tools/

나는 몇 년 전에 일했습니다.

효율성에 기존의 문제가 있습니까?

그렇다면 항상 코드 (또는 의사 코드)를 게시하면 시체에서 선택할 수 있습니다.

그렇지 않다면 항목을 정렬 된 목록에 저장하고 환경의 기존 사용과 같은 간단한 것을 시도하는 것이 좋습니다. Sort() 그리고 Find().

정수 비교는 문자열 비교보다 훨씬 빠릅니다.

정렬 된 목록에 정수를 저장하는 경우, 분류되지 않은 목록보다 더 빨리 찾을 수 있습니다.

IP 주소를 문자열로 수신하는 경우 문자열과 비교하는 것이 정수 표현으로 변환하는 것보다 더 효율적일 수 있습니다.

그러나 나는이 작업에서 몇 밀리 초 (나노초)가 중요 할 경우 두 솔루션을 모두 확신 할 수 있도록 프로파일 링 ;-)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top