2012-05-09 36 views
7

Nếu tôi có một dải địa chỉ IP (ký hiệu CIDR) và tôi cần biết nếu một số địa chỉ IP tùy ý nằm trong phạm vi đó - cả hai được trình bày dưới dạng chuỗi - cách dễ nhất để làm điều này với C# là gì?Cách so sánh dải địa chỉ IP trong C#?

Ví dụ:

  • IPv4 Phạm vi: 192.168.168.100/24, IP để kiểm tra: 192.168.168.200
  • IPv6 Phạm vi: fe80::202:b3ff:fe1e:8329/24, IP để kiểm tra: 2001:db8::
+0

Bạn có muốn xem giải pháp chỉ IPv4 không? – Tung

+0

Số ipv4 là khá dễ dàng. Điều gì làm cho nó thách thức là ipv6, hoặc khi hai định dạng được trộn lẫn. Đánh giá bởi sự thiếu phản ứng ở đây, có vẻ như không nhiều người quan tâm đến nó ... – ahmd0

Trả lời

10

Dưới đây là một lớp đơn giản: sử dụng

public class IPSubnet 
{ 
    private readonly byte[] _address; 
    private readonly int _prefixLength; 

    public IPSubnet(string value) 
    { 
     if (value == null) 
      throw new ArgumentNullException("value"); 

     string[] parts = value.Split('/'); 
     if (parts.Length != 2) 
      throw new ArgumentException("Invalid CIDR notation.", "value"); 

     _address = IPAddress.Parse(parts[0]).GetAddressBytes(); 
     _prefixLength = Convert.ToInt32(parts[1], 10); 
    } 

    public bool Contains(string address) 
    { 
     return this.Contains(IPAddress.Parse(address).GetAddressBytes()); 
    } 

    public bool Contains(byte[] address) 
    { 
     if (address == null) 
      throw new ArgumentNullException("address"); 

     if (address.Length != _address.Length) 
      return false; // IPv4/IPv6 mismatch 

     int index = 0; 
     int bits = _prefixLength; 

     for (; bits >= 8; bits -= 8) 
     { 
      if (address[index] != _address[index]) 
       return false; 
      ++index; 
     } 

     if (bits > 0) 
     { 
      int mask = (byte)~(255 >> bits); 
      if ((address[index] & mask) != (_address[index] & mask)) 
       return false; 
     } 

     return true; 
    } 
} 

mẫu:

xử lý
Console.WriteLine(new IPSubnet("192.168.168.100/24").Contains("192.168.168.200")); // True 
Console.WriteLine(new IPSubnet("fe80::202:b3ff:fe1e:8329/24").Contains("2001:db8::")); // False 

Lớp này tất cả các địa chỉ IPv4 như khác biệt với tất cả các địa chỉ IPv6, làm cho không cố gắng dịch giữa IPv4 và IPv6.

+0

Cảm ơn. Mặc dù IPv4 nên được chuyển đổi sang IPv6, ví dụ, người ta có thể sử dụng ":: 192.168.168.100" sẽ được coi là IPv6 theo mã của bạn. – ahmd0

+1

Bạn có chắc chắn là đúng để chuyển đổi địa chỉ IPv4 thành IPv6 bằng cách chỉ cần thêm tiền tố vào "@"? Bài viết trên [Wikipedia address] (http://en.wikipedia.org/wiki/IPv6_address#Special_addresses) Wikipedia không liệt kê đây là một trong những cơ chế dịch thuật IPv4. –

+0

Xin lỗi vì sự chậm trễ này. Tôi tìm thấy nó trực tuyến, nếu bạn tìm kiếm "chuyển đổi Ipv4 để IPv6." Vì vậy, tôi không biết ... – ahmd0

2
+1

Vâng, quá tệ, bởi vì nó không phải là rất rõ ràng làm thế nào để làm so sánh này. Ví dụ: nếu phạm vi có ký hiệu ipv6 nhưng địa chỉ là ipv4 và ngược lại thì sao? Cũng chỉ cần áp dụng mặt nạ mạng con cho địa chỉ ipv6 cũng không rõ ràng. Và không có nhiều ví dụ về nó trên web ... – ahmd0

+0

Tôi không chắc ý bạn là gì? IPv4 và IPv6 là 2 thứ hoàn toàn khác nhau. Không có IPv4 nào có ký hiệu IPv6. Tôi sẽ không điều trị :: 192.168.1.1 giống với địa chỉ IPv6 khác. – LukeP

1

Tôi khuyên bạn nên sử dụng Thư viện IPNetwork https://github.com/lduchosal/ipnetwork. Kể từ phiên bản 2, nó cũng hỗ trợ IPv4 và IPv6.

IPv6

IPNetwork ipnetwork = IPNetwork.Parse("fe80::202:b3ff:fe1e:8329/24"); 

    IPAddress ipaddress = IPAddress.Parse("2001:db8::"); 
    IPAddress ipaddress2 = IPAddress.Parse("fe80::202:b3ff:fe1e:1"); 

    bool contains1 = IPNetwork.Contains(ipnetwork, ipaddress); 
    bool contains2 = IPNetwork.Contains(ipnetwork, ipaddress2); 

    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress,  contains1); 
    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress2,  contains2); 

Output

fe80::/24 contains 2001:db8:: : False 
    fe80::/24 contains fe80::202:b3ff:fe1e:1 : True 

IPv4

IPNetwork ipnetwork = IPNetwork.Parse("192.168.168.100/24"); 

    IPAddress ipaddress = IPAddress.Parse("192.168.168.200"); 
    IPAddress ipaddress2 = IPAddress.Parse("192.168.0.200"); 

    bool contains1 = IPNetwork.Contains(ipnetwork, ipaddress); 
    bool contains2 = IPNetwork.Contains(ipnetwork, ipaddress2); 

    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress, contains1); 
    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress2, contains2); 

Output

192.168.168.0/24 contains 192.168.168.200 : True 
    192.168.168.0/24 contains 192.168.0.200 : False 

Hãy vui vẻ!

Các vấn đề liên quan