2016-10-14 3 views
-1

내가 (특히 도시/국가 수준까지) Maxmind의 위치 정보 테이블을 사용하고, 이러한 테이블 중 하나는이 구조가 있습니다 enter image description here독립형 IP를 CIDR과 어떻게 일치시킬 수 있습니까?

내가 다른 테이블에서 내 서비스의 사용자의 IP를 저장을; latitudelongitude 열을 생성했으며 해당 IP의 해당 위도 및 경도를 IP 테이블의 해당 테이블에 저장합니다.

MaxMind 테이블의 IP는 CIDR 형식으로 저장됩니다. 즉, 은 직접이 CIDR에 지정된 IP 범위 내에 들어가는 지 확인하지 못합니다.

MySQL 문만을 사용하여 일반 IP를 CIDR 형식으로 일치시킬 수 있습니까?

나는이 시도했지만 발견 그러나 다음과 같은 : 그것은

  • 수하지만, 나는 (내가 가지고 있지 않는) 서브넷 마스크가 필요
  • I 서브넷를 얻을 수 있습니다

MaxMind 테이블에서 CIDR 표기법에 users 테이블에 IP를 일치하는 것은 시간이 걸릴 것으로, 내가저기서거야 ... 그러나 그것은 CIDR을 필요로 원시 IP에서 마스크 조지아 표준 C#의 CLI 프로그램은 일괄 처리하고, 나는이 할 수 있음을 인정하는

  1. 는 데이터 판독기
  2. 이동 각 행 불구로하여 전체 MaxMind 테이블을 검색을하고에 CIDR로 변환 동시에, IP 범위
  3. users 테이블 데이터 판독기를 열고 IP 범위에 지정된 IP 일치
  4. UPDATE 이전
  5. 에서 CIDR 일치하는 위도 및 경도와 users의 해당 레코드

알다시피 내 방법은 (나에게는) 매우 비효율적 인 것으로 보이며, 필요한 것보다 훨씬 더 많은 시간이 걸릴 수 있습니다.


단순히 MySQL 문을 사용하여 일반 IP를 CIDR과 일치시킬 수 있습니까? 그렇지 않다면 없이 서브넷 마스크없이 IP 범위를 계산 한 다음 IP를 일치시킬 수 있습니까? 다음과 같이 users 테이블에 관련된

열은 다음과 같습니다

enter image description here

+0

"단순히 MySQL 문을 사용하여 일반 IP를 CIDR과 일치시킬 수 있습니까?" 아니오. "서브넷 마스크없이 IP 범위를 계산 한 다음 IP를 일치시킬 수 있습니까?" 서브넷 마스크가없는 범위를 어떻게 알 수 있습니까? – itsme86

+0

한 가지 방법은 열을 추가하는 것입니다. CIDR은 결국 주소의 네트워크 부분의 비트 마스크 일 뿐이므로 각 범위에 대해 네트워크 부분 (정수)이있는 열이 있습니다. 그러면 원하는 IP를 가져올 수 있습니다 마지막에 네트워크 부분을 더 짧고 짧게 만들 때까지 매치되거나 비트가 다 떨어질 때까지 기다리십시오. 그것은 <23 쿼리가 될 것입니다. 무력과 추한. MySQL로 할 수 있습니까? 나는 놀랄 것이다. – Duston

+0

@ itsme86 유료 Geolocation 서비스에 의지하지 않고 사용자가 사용할 수있는 IP를 위도와 경도를 'users' 테이블에 저장하는 방법을 찾으려고합니다. – cybermonkey

답변

0

도움이된다면, 내가 IP 주소 범위 내에있는 경우 확인하기 위해 몇 시간 전에이 클래스를 썼다. 네트워크와 마스크를 CIDR 문자열로 분할하고 구문 분석 한 다음 생성자로 전달해야합니다. 그런 다음 ContainsIP()을 사용하여 IP 주소가 해당 네트워크에 속하는지 확인할 수 있습니다. 그것은 아마 당신을 위해 분할/파싱을 처리하기 위해 CIDR 문자열을 받아들이는 다른 생성자를 사용할 수 있습니다.

public class IPNetwork 
{ 
    private readonly IPAddress _networkMask; 
    private readonly int _networkMaskLength; 
    private readonly uint _networkMaskValue; 

    public IPNetwork(IPAddress networkMask, int networkMaskLength) 
    { 
     if (networkMask.AddressFamily != AddressFamily.InterNetwork) 
      throw new InvalidOperationException("Only IPv4 networks are supported."); 

     _networkMask = networkMask; 
     _networkMaskLength = networkMaskLength; 
     _networkMaskValue = GetMaskedAddress(networkMask); 
    } 

    public bool ContainsIP(IPAddress ipAddress) 
    { 
     return GetMaskedAddress(ipAddress) == _networkMaskValue; 
    } 

    private uint GetMaskedAddress(IPAddress ipAddress) 
    { 
     byte[] bytes = ipAddress.GetAddressBytes(); 
     int addressLength = bytes.Length * 8; 
     uint addressValue = BytesToValue(bytes); 

     uint maskedAddress = 0; 
     for (int i = addressLength - _networkMaskLength; i < addressLength; ++i) 
      maskedAddress |= addressValue & (1U << i); 

     return maskedAddress; 
    } 

    private uint BytesToValue(byte[] bytes) 
    { 
     uint value = 0; 

     for (int i = 0; i < bytes.Length; ++i) 
      value |= (uint)(bytes[bytes.Length - i - 1] << (i * 8)); 

     return value; 
    } 
} 
관련 문제