2009-09-30 244 views

回答

23

采取在MSDN博客看看IP Address Calculations with C#。它包含一个扩展方法(IsInSameSubnet),可以满足您的需求以及其他一些好处。

public static class IPAddressExtensions 
{ 
    public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask) 
    { 
     byte[] ipAdressBytes = address.GetAddressBytes(); 
     byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); 

     if (ipAdressBytes.Length != subnetMaskBytes.Length) 
      throw new ArgumentException("Lengths of IP address and subnet mask do not match."); 

     byte[] broadcastAddress = new byte[ipAdressBytes.Length]; 
     for (int i = 0; i < broadcastAddress.Length; i++) 
     { 
      broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i]^255)); 
     } 
     return new IPAddress(broadcastAddress); 
    } 

    public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask) 
    { 
     byte[] ipAdressBytes = address.GetAddressBytes(); 
     byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); 

     if (ipAdressBytes.Length != subnetMaskBytes.Length) 
      throw new ArgumentException("Lengths of IP address and subnet mask do not match."); 

     byte[] broadcastAddress = new byte[ipAdressBytes.Length]; 
     for (int i = 0; i < broadcastAddress.Length; i++) 
     { 
      broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i])); 
     } 
     return new IPAddress(broadcastAddress); 
    } 

    public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask) 
    { 
     IPAddress network1 = address.GetNetworkAddress(subnetMask); 
     IPAddress network2 = address2.GetNetworkAddress(subnetMask); 

     return network1.Equals(network2); 
    } 
} 
+0

IPv6地址如何? – ageroh 2017-11-13 14:32:21

+0

@ageroh GitHub似乎有几个可以处理IPv6地址的C#库。 IPNetwork,例如https://github.com/lduchosal/ipnetwork – 2017-11-13 18:20:57

10

位操作工作。东西IP为32位无符号整数,做子网的地址,& -mask都同样具有0xFFFFFFFF << (32-20)和比较:

unsigned int net = ..., ip = ...; 
int network_bits = 20; 
unsigned int mask = 0xFFFFFFFF << (32 - network_bits); 
if ((net & mask) == (ip & mask)) { 
    // ... 
} 
+0

或者,如果作为普通,子网给出一个数字,如255.255.240.0,只是东西将掩码转换为32位整数而不是移位。 – erikkallen 2009-09-30 16:39:02

+3

我发现System.Net.IPAddress类有助于解析和分解IP地址为字节 – 2009-09-30 19:12:01

0

的解决方案是将IP地址转换成使用System.Net.IPAddress字节上的地址,子网和掩模八位位组按位进行比较。

二进制AND运算符&如果它们存在于两个操作数中,则将结果复制一位。

代码:

using System.Net; // Used to access IPAddress 

bool IsAddressOnSubnet(string address, string subnet, string mask) 
{ 
    try 
    { 
     IPAddress Address = IPAddress.Parse(address); 
     IPAddress Subnet = IPAddress.Parse(subnet); 
     IPAddress Mask = IPAddress.Parse(mask);    

     Byte[] addressOctets = Address.GetAddressBytes(); 
     Byte[] subnetOctets = Mask.GetAddressBytes(); 
     Byte[] networkOctets = Subnet.GetAddressBytes(); 

     return 
      ((networkOctets[0] & subnetOctets[0]) == (addressOctets[0] & subnetOctets[0])) && 
      ((networkOctets[1] & subnetOctets[1]) == (addressOctets[1] & subnetOctets[1])) && 
      ((networkOctets[2] & subnetOctets[2]) == (addressOctets[2] & subnetOctets[2])) && 
      ((networkOctets[3] & subnetOctets[3]) == (addressOctets[3] & subnetOctets[3])); 
    } 
    catch (System.Exception ex) 
    { 
     return false;     
    } 
} 

特别感谢Спасибо! Прекрасноерешение! Reference

+1

只是要知道,如果出现IPv6地址,这会中断 – Fowl 2016-07-28 04:24:40

2

由于MSDN博客代码依赖于广播,而IPv6没有广播,所以我不知道它是否适用于IPv6。

我结束了这些方法(感谢nu珠穆朗玛峰)。您可以从CIDR表示法(“1.2.3.4/5”)获取子网和掩码,并检查地址是否在该网络中。

这适用于IPv4和IPv6:

public static class IpAddresses 
{ 
    public static Tuple<IPAddress, IPAddress> GetSubnetAndMaskFromCidr(string cidr) 
    { 
     var delimiterIndex = cidr.IndexOf('/'); 
     string ipSubnet = cidr.Substring(0, delimiterIndex); 
     string mask = cidr.Substring(delimiterIndex + 1); 

     var subnetAddress = IPAddress.Parse(ipSubnet); 

     if (subnetAddress.AddressFamily == AddressFamily.InterNetworkV6) 
     { 
      // ipv6 
      var ip = BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber) << (128 - int.Parse(mask)); 

      var maskBytes = new[] 
      { 
       (byte)((ip & BigInteger.Parse("00FF000000000000000000000000000000", NumberStyles.HexNumber)) >> 120), 
       (byte)((ip & BigInteger.Parse("0000FF0000000000000000000000000000", NumberStyles.HexNumber)) >> 112), 
       (byte)((ip & BigInteger.Parse("000000FF00000000000000000000000000", NumberStyles.HexNumber)) >> 104), 
       (byte)((ip & BigInteger.Parse("00000000FF000000000000000000000000", NumberStyles.HexNumber)) >> 96), 
       (byte)((ip & BigInteger.Parse("0000000000FF0000000000000000000000", NumberStyles.HexNumber)) >> 88), 
       (byte)((ip & BigInteger.Parse("000000000000FF00000000000000000000", NumberStyles.HexNumber)) >> 80), 
       (byte)((ip & BigInteger.Parse("00000000000000FF000000000000000000", NumberStyles.HexNumber)) >> 72), 
       (byte)((ip & BigInteger.Parse("0000000000000000FF0000000000000000", NumberStyles.HexNumber)) >> 64), 
       (byte)((ip & BigInteger.Parse("000000000000000000FF00000000000000", NumberStyles.HexNumber)) >> 56), 
       (byte)((ip & BigInteger.Parse("00000000000000000000FF000000000000", NumberStyles.HexNumber)) >> 48), 
       (byte)((ip & BigInteger.Parse("0000000000000000000000FF0000000000", NumberStyles.HexNumber)) >> 40), 
       (byte)((ip & BigInteger.Parse("000000000000000000000000FF00000000", NumberStyles.HexNumber)) >> 32), 
       (byte)((ip & BigInteger.Parse("00000000000000000000000000FF000000", NumberStyles.HexNumber)) >> 24), 
       (byte)((ip & BigInteger.Parse("0000000000000000000000000000FF0000", NumberStyles.HexNumber)) >> 16), 
       (byte)((ip & BigInteger.Parse("000000000000000000000000000000FF00", NumberStyles.HexNumber)) >> 8), 
       (byte)((ip & BigInteger.Parse("00000000000000000000000000000000FF", NumberStyles.HexNumber)) >> 0), 
      }; 

      return Tuple.Create(subnetAddress, new IPAddress(maskBytes)); 
     } 
     else 
     { 
      // ipv4 
      uint ip = 0xFFFFFFFF << (32 - int.Parse(mask)); 

      var maskBytes = new[] 
      { 
       (byte)((ip & 0xFF000000) >> 24), 
       (byte)((ip & 0x00FF0000) >> 16), 
       (byte)((ip & 0x0000FF00) >> 8), 
       (byte)((ip & 0x000000FF) >> 0), 
      }; 

      return Tuple.Create(subnetAddress, new IPAddress(maskBytes)); 
     } 
    } 

    public static bool IsAddressOnSubnet(IPAddress address, IPAddress subnet, IPAddress mask) 
    { 
     byte[] addressOctets = address.GetAddressBytes(); 
     byte[] subnetOctets = mask.GetAddressBytes(); 
     byte[] networkOctets = subnet.GetAddressBytes(); 

     // ensure that IPv4 isn't mixed with IPv6 
     if (addressOctets.Length != subnetOctets.Length 
      || addressOctets.Length != networkOctets.Length) 
     { 
      return false; 
     } 

     for (int i = 0; i < addressOctets.Length; i += 1) 
     { 
      var addressOctet = addressOctets[i]; 
      var subnetOctet = subnetOctets[i]; 
      var networkOctet = networkOctets[i]; 

      if (networkOctet != (addressOctet & subnetOctet)) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
} 

用法示例:

var subnetAndMask = IpAddresses.GetSubnetAndMaskFromCidr("10.132.0.0/20"); 
bool result = IpAddresses.IsAddressOnSubnet(
    IPAddress.Parse("10.132.12.34"), 
    subnetAndMask.Item1, 
    subnetAndMask.Item2); 
0

,我迟到了这里,但也有类似的需求,以及快速包放在一起做到这一点。

https://www.nuget.org/packages/IpMatcher/

和来源:

https://github.com/jchristn/IpMatcher

简单的使用:

using IpMatcher; 

Matcher matcher = new Matcher(); 
matcher.Add("192.168.1.0", "255.255.255.0"); 
matcher.Add("192.168.2.0", "255.255.255.0"); 
matcher.Remove("192.168.2.0"); 
matcher.Exists("192.168.1.0", "255.255.255.0"); // true 
matcher.Match("192.168.1.34"); // true 
matcher.Match("10.10.10.10"); // false 
相关问题