2010-01-26 62 views
51

如果我们让用户输入几个IP范围,例如172.16.11.5-100,我该如何编写一个函数来检查IP(172.16.11.50)在范围内?如何检查输入IP是否落在特定的IP范围

.NET中是否有任何现有的库可以利用?

+0

一个值得注意的问题 - 如果要实现这个以查看是否有IP是在一个特定的子网,那么你就不能可靠地做到这一点没有考虑到子网掩码为好。 – 2010-01-26 10:28:56

+0

看起来他并没有指定子网掩码。如果他是你使用单个IP并指定子网,而不是一个IP地址范围。范围内的正常使用,因为洛塔人不知道什么子网的是... – Ian 2010-01-26 10:55:34

+0

类似于/可能重复 - http://stackoverflow.com/questions/1820661/comparing-ipaddress-stored-as-varbinary/1821016#1821016 – ram 2010-01-26 20:09:32

回答

98

框架没有内置任何东西,但创建IPAddressRange类并不需要太多的努力。

您可以通过调用IPAddress.GetAddressBytes的较低地址,较高地址和比较地址来比较范围。从第一个字节开始,检查比较地址是否在上/下地址范围内。

此方法适用于IPv4和IPv6地址。

public class IPAddressRange 
{ 
    readonly AddressFamily addressFamily; 
    readonly byte[] lowerBytes; 
    readonly byte[] upperBytes; 

    public IPAddressRange(IPAddress lowerInclusive, IPAddress upperInclusive) 
    { 
     // Assert that lower.AddressFamily == upper.AddressFamily 

     this.addressFamily = lowerInclusive.AddressFamily; 
     this.lowerBytes = lowerInclusive.GetAddressBytes(); 
     this.upperBytes = upperInclusive.GetAddressBytes(); 
    } 

    public bool IsInRange(IPAddress address) 
    { 
     if (address.AddressFamily != addressFamily) 
     { 
      return false; 
     } 

     byte[] addressBytes = address.GetAddressBytes(); 

     bool lowerBoundary = true, upperBoundary = true; 

     for (int i = 0; i < this.lowerBytes.Length && 
      (lowerBoundary || upperBoundary); i++) 
     { 
      if ((lowerBoundary && addressBytes[i] < lowerBytes[i]) || 
       (upperBoundary && addressBytes[i] > upperBytes[i])) 
      { 
       return false; 
      } 

      lowerBoundary &= (addressBytes[i] == lowerBytes[i]); 
      upperBoundary &= (addressBytes[i] == upperBytes[i]); 
     } 

     return true; 
    } 
} 

注:上面的代码可以扩展到公共添加静态工厂方法FromCidr(IPAddress address, int bits)

+1

这将是虚假的情况下:下 - 222.168.2.1,上 - 222.168.5.10和目标 - 222.168.3.55 – Ricky 2010-01-27 08:49:28

+1

好一点。查看更新版本。 – 2010-01-27 10:12:04

+2

杰出贡献,@理查德。巨大的帮助我。 – egandalf 2013-01-23 21:21:06

8

最好的办法是将这些地址转换为整数,然后执行比较。从这里

例子:IP to Integer

要转换的IP地址为整数,它分成四个八位字节。例如,您提供的IP地址可以分解为:

First Octet: 217 
Second Octet: 110 
Third Octet: 18 
Fourth Octet: 206 

要从虚线字符串计算小数地址,请执行以下计算。

(first octet * 256³) + (second octet * 256²) + (third octet * 256) + (fourth octet) 
= (first octet * 16777216) + (second octet * 65536) + (third octet * 256) + (fourth octet) 
= (217 * 16777216) + (110 * 65536) + (18 * 256) + (206) 
= 3647869646 

考虑IPv6,可以将它们转换为整数(128位VS 32位的IPv4)为好。看看这个问题:Formatting IPv6 as an int in C# and storing it in SQL Server

最简单的途径是让 框架来为你做这个。使用 IPAddress.Parse解析地址, 然后IPAddress.GetAddressBytes得到 的“数字”为byte[]

+1

这不适用于IPAddress类支持的IPv6地址。 – 2010-01-26 10:20:35

1

你可以找出从您的IP范围的subnet mask

如果是的话,也许你可以使用这个方法IsInSameSubnet ..

+0

您可以拥有多个具有相同子网掩码的网络。我不会相信这种方式。 – dampee 2011-09-09 08:41:20

3

重新发布我的回答从here

前一段时间,我必须找到一个给定的IP位置。我们从请求中获得了IP。有免费的数据库给了我们这个映射。在IPv4中,当我们将IP称为“a.b.c.d”时,它基本上是*(256^3)+ b *(256^2)+ c *(256)+ d。

http://www.aboutmyip.com/AboutMyXApp/IP2Integer.jsp

所以当你说你想要一个IP地址从 “a”,你正在寻找一个* 256^3和*之间的IP 256^3 + 256 *(256^2)( b = 256)+ 256 *(256)(c = 256)+ 256(d = 256)(取决于是否包含/不包含限制,更低/上限可能会有所不同)。

也就是说,为特定目的保留了特定的IP(如127.0.0.1是localhost,0.0.0.0不能是IP等)。

所以,你的LINQ查询会

“从我在ILIST其中i> = MIN & &我< = MAX选择我;”

其中ILIST是你最初的名单MIN是你的范围的最小值MAX是你的范围的最大值

9
public static bool IsInRange(string startIpAddr, string endIpAddr, string address) 
{ 
    long ipStart = BitConverter.ToInt32(IPAddress.Parse(startIpAddr).GetAddressBytes().Reverse().ToArray(), 0); 

    long ipEnd = BitConverter.ToInt32(IPAddress.Parse(endIpAddr).GetAddressBytes().Reverse().ToArray(), 0); 

    long ip = BitConverter.ToInt32(IPAddress.Parse(address).GetAddressBytes().Reverse().ToArray(), 0); 

    return ip >= ipStart && ip <= ipEnd; //edited 
} 

Console.WriteLine(IsInRange("100.0.0.1", "110.0.0.255", "102.0.0.4"));//true 
+6

我会说相等也落在范围内:return ip> = ipStart && ip <= ipEnd; – Jannes 2013-01-03 11:15:36

+0

完美答案!这通过了我所有的单元测试,尤其是范围的低端。 – 2014-10-01 18:32:55

+2

Erm,我们不应该使用'UInt32'而不是'long'或'Int32'吗?这不会在任何地址范围桥接或128.0.0.0以上失败? – 2016-03-20 23:20:45