C#:枚举范围内的IP地址

如何遍历用户提供的一系列IP地址?

我对格式很灵活,只要它允许指定所有范围。 也许像nmap风格的东西:

'192.0.2.1' # one IP address '192.0.2.0-31' # one block with 32 IP addresses. '192.0.2-3.1-254' # two blocks with 254 IP addresses. '0-255.0-255.0-255.0-255' # the whole IPv4 address space 

例如,如果用户输入192.0.2-3.1-254 ,我想知道如何生成此范围内所有有效IP地址的列表,以便我可以迭代它们。

例如:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Text.RegularExpressions; namespace IpRanges { public class IPRange { public IPRange(string ipRange) { if (ipRange == null) throw new ArgumentNullException(); if (!TryParseCIDRNotation(ipRange) && !TryParseSimpleRange(ipRange)) throw new ArgumentException(); } public IEnumerable GetAllIP() { int capacity = 1; for (int i = 0; i < 4; i++) capacity *= endIP[i] - beginIP[i] + 1; List ips = new List(capacity); for (int i0 = beginIP[0]; i0 <= endIP[0]; i0++) { for (int i1 = beginIP[1]; i1 <= endIP[1]; i1++) { for (int i2 = beginIP[2]; i2 <= endIP[2]; i2++) { for (int i3 = beginIP[3]; i3 <= endIP[3]; i3++) { ips.Add(new IPAddress(new byte[] { (byte)i0, (byte)i1, (byte)i2, (byte)i3 })); } } } } return ips; } ///  /// Parse IP-range string in CIDR notation. /// For example "12.15.0.0/16". ///  ///  ///  private bool TryParseCIDRNotation(string ipRange) { string[] x = ipRange.Split('/'); if (x.Length != 2) return false; byte bits = byte.Parse(x[1]); uint ip = 0; String[] ipParts0 = x[0].Split('.'); for (int i = 0; i < 4; i++) { ip = ip << 8; ip += uint.Parse(ipParts0[i]); } byte shiftBits = (byte)(32 - bits); uint ip1 = (ip >> shiftBits) << shiftBits; if (ip1 != ip) // Check correct subnet address return false; uint ip2 = ip1 >> shiftBits; for (int k = 0; k < shiftBits; k++) { ip2 = (ip2 << 1) + 1; } beginIP = new byte[4]; endIP = new byte[4]; for (int i = 0; i < 4; i++) { beginIP[i] = (byte) ((ip1 >> (3 - i) * 8) & 255); endIP[i] = (byte)((ip2 >> (3 - i) * 8) & 255); } return true; } ///  /// Parse IP-range string "12.15-16.1-30.10-255" ///  ///  ///  private bool TryParseSimpleRange(string ipRange) { String[] ipParts = ipRange.Split('.'); beginIP = new byte[4]; endIP = new byte[4]; for (int i = 0; i < 4; i++) { string[] rangeParts = ipParts[i].Split('-'); if (rangeParts.Length < 1 || rangeParts.Length > 2) return false; beginIP[i] = byte.Parse(rangeParts[0]); endIP[i] = (rangeParts.Length == 1) ? beginIP[i] : byte.Parse(rangeParts[1]); } return true; } private byte [] beginIP; private byte [] endIP; } } 

看看这里的片段。 请妥善保管学分。

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Net; /* ==================================================================================== C# IP address range finder helper class (C) Nahum Bazes * Free for private & commercial use - no restriction applied, please leave credits. * DO NOT REMOVE THIS COMMENT * ==================================================================================== */ namespace IPAddressTools { public class RangeFinder { public IEnumerable GetIPRange(IPAddress startIP, IPAddress endIP) { uint sIP = ipToUint(startIP.GetAddressBytes()); uint eIP = ipToUint(endIP.GetAddressBytes()); while (sIP <= eIP) { yield return new IPAddress(reverseBytesArray(sIP)).ToString(); sIP++; } } /* reverse byte order in array */ protected uint reverseBytesArray(uint ip) { byte[] bytes = BitConverter.GetBytes(ip); bytes = bytes.Reverse().ToArray(); return (uint)BitConverter.ToInt32(bytes, 0); } /* Convert bytes array to 32 bit long value */ protected uint ipToUint(byte[] ipBytes) { ByteConverter bConvert = new ByteConverter(); uint ipUint = 0; int shift = 24; // indicates number of bits left for shifting foreach (byte b in ipBytes) { if (ipUint == 0) { ipUint = (uint)bConvert.ConvertTo(b, typeof(uint)) << shift; shift -= 8; continue; } if (shift >= 8) ipUint += (uint)bConvert.ConvertTo(b, typeof(uint)) << shift; else ipUint += (uint)bConvert.ConvertTo(b, typeof(uint)); shift -= 8; } return ipUint; } } } 

我认为应该这样做。

 static void TestFunc() { byte[,] range = ParseRange("192.0.2-5.14-28"); foreach (IPAddress addr in Enumerate(range)) { Console.WriteLine(addr); } } static byte[,] ParseRange(string str) { if (string.IsNullOrEmpty(str)) throw new ArgumentException("str"); string[] partStr = str.Split('.'); if (partStr.Length != 4) throw new FormatException(); byte[,] range = new byte[4, 2]; for (int i = 0; i < 4; i++) { string[] rangeStr = partStr[i].Split('-'); if (rangeStr.Length > 2) throw new FormatException(); range[i, 0] = byte.Parse(rangeStr[0]); range[i, 1] = byte.Parse(rangeStr[Math.Min(rangeStr.Length - 1, 1)]); // Remove this to allow ranges to wrap around. // For example: 254-4 = 254, 255, 0, 1, 2, 3, 4 if (range[i, 1] < range[i, 0]) throw new FormatException(); } return range; } static IEnumerable Enumerate(byte[,] range) { if (range.GetLength(0) != 4) throw new ArgumentException("range"); if (range.GetLength(1) != 2) throw new ArgumentException("range"); for (byte a = range[0, 0]; a != (byte)(range[0, 1] + 1); a++) { for (byte b = range[1, 0]; b != (byte)(range[1, 1] + 1); b++) { for (byte c = range[2, 0]; c != (byte)(range[2, 1] + 1); c++) { for (byte d = range[3, 0]; d != (byte)(range[3, 1] + 1); d++) { yield return new IPAddress(new byte[] { a, b, c, d }); } } } } } 

我迟到了,但你的问题一式两份提到,所以我只想在这里添加答案。 使用IPAddressRange库,您可以枚举您的IP:

 var start = IPAddress.Parse("192.168.0.2"); var end = IPAddress.Parse("192.168.0.254"); var range = new IPAddressRange(start, end); foreach (var ip in range) { Console.WriteLine(ip); } 

该库还支持CIDR表示法和范围字符串