如果我们让用户输入几个IP范围,例如172.16.11.5-100,我该如何编写一个函数来检查IP(172.16.11.50)在范围内?如何检查输入IP是否落在特定的IP范围
.NET中是否有任何现有的库可以利用?
如果我们让用户输入几个IP范围,例如172.16.11.5-100,我该如何编写一个函数来检查IP(172.16.11.50)在范围内?如何检查输入IP是否落在特定的IP范围
.NET中是否有任何现有的库可以利用?
框架没有内置任何东西,但创建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)
最好的办法是将这些地址转换为整数,然后执行比较。从这里
要转换的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[]
。
这不适用于IPAddress类支持的IPv6地址。 – 2010-01-26 10:20:35
你可以找出从您的IP范围的subnet mask?
如果是的话,也许你可以使用这个方法IsInSameSubnet ..
您可以拥有多个具有相同子网掩码的网络。我不会相信这种方式。 – dampee 2011-09-09 08:41:20
我之前使用在CodeProject上的代码,这可能是你有帮助。
重新发布我的回答从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是你的范围的最大值
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
我会说相等也落在范围内:return ip> = ipStart && ip <= ipEnd; – Jannes 2013-01-03 11:15:36
完美答案!这通过了我所有的单元测试,尤其是范围的低端。 – 2014-10-01 18:32:55
Erm,我们不应该使用'UInt32'而不是'long'或'Int32'吗?这不会在任何地址范围桥接或128.0.0.0以上失败? – 2016-03-20 23:20:45
对于任何人谁在这个问题上检查:
你可能要考虑该库由@jsakamoto,这似乎工作得精细:
https://github.com/jsakamoto/ipaddressrange
它也可以通过的NuGet安装:
一个值得注意的问题 - 如果要实现这个以查看是否有IP是在一个特定的子网,那么你就不能可靠地做到这一点没有考虑到子网掩码为好。 – 2010-01-26 10:28:56
看起来他并没有指定子网掩码。如果他是你使用单个IP并指定子网,而不是一个IP地址范围。范围内的正常使用,因为洛塔人不知道什么子网的是... – Ian 2010-01-26 10:55:34
类似于/可能重复 - http://stackoverflow.com/questions/1820661/comparing-ipaddress-stored-as-varbinary/1821016#1821016 – ram 2010-01-26 20:09:32