如果我们让用户输入几个ip范围,例如172.16.11.5 - 100,我怎么能写一个函数来检查IP(172.16.11.50)是否属于范围?
是否有任何现有的.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)
您可能希望通过@jsakamoto考虑此库,它允许您解析IP地址字符串的范围,例如"192.168.0.0/24"和"192.168.0.0/255.255.255.0"和"192.168.0.0-192.168.0.255" ,并可以检查.该库支持IPv4和IPv6.
https://github.com/jsakamoto/ipaddressrange
它也可以通过NuGet安装:
http://www.nuget.org/packages/IPAddressRange/
using NetTools; ... // rangeA.Begin is "192.168.0.0", and rangeA.End is "192.168.0.255". var rangeA = IPAddressRange.Parse("192.168.0.0/255.255.255.0"); rangeA.Contains(IPAddress.Parse("192.168.0.34")); // is True. rangeA.Contains(IPAddress.Parse("192.168.10.1")); // is False. rangeA.ToCidrString(); // is 192.168.0.0/24 // rangeB.Begin is "192.168.0.10", and rangeB.End is "192.168.10.20". var rangeB1 = IPAddressRange.Parse("192.168.0.10 - 192.168.10.20"); rangeB1.Contains(IPAddress.Parse("192.168.3.45")); // is True. rangeB1.Contains(IPAddress.Parse("192.168.0.9")); // is False. // Support shortcut range description. // ("192.168.10.10-20" means range of begin:192.168.10.10 to end:192.168.10.20.) var rangeB2 = IPAddressRange.Parse("192.168.10.10-20"); // Support CIDR expression and IPv6. var rangeC = IPAddressRange.Parse("fe80::/10"); rangeC.Contains(IPAddress.Parse("fe80::d503:4ee:3882:c586%3")); // is True. rangeC.Contains(IPAddress.Parse("::1")); // is False.
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
最好是将这些地址转换为整数,然后执行比较.
示例来自:IP到整数
要将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位与32位IPv4).看看这个问题:将IPv6格式化为C#中的int并将其存储在SQL Server中
最简单的方法是让框架为您完成此操作.使用
IPAddress.Parse
解析地址,然后IPAddress.GetAddressBytes
获得"数字"作为byte[]
.