2010-11-13 5 views
17

Wie durchläuft ich eine Reihe von IP-Adressen, die vom Benutzer bereitgestellt werden?C#: Aufzählung von IP-Adressen in einem Bereich

Ich bin flexibel auf das Format, vorausgesetzt, es ermöglicht die Angabe aller Bereiche. Vielleicht so etwas wie der nmap-style:

'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 

Zum Beispiel, wenn der Benutzer 192.0.2-3.1-254 eingegeben, würde Ich mag wissen, wie man eine Liste aller gültigen IP-Adressen in diesem Bereich zu erzeugen, so dass ich durch sie durchlaufen konnte .

Antwort

19

Zum Beispiel:

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<IPAddress> GetAllIP() 
     { 
      int capacity = 1; 
      for (int i = 0; i < 4; i++) 
       capacity *= endIP[i] - beginIP[i] + 1; 

      List<IPAddress> ips = new List<IPAddress>(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; 
     } 

     /// <summary> 
     /// Parse IP-range string in CIDR notation. 
     /// For example "12.15.0.0/16". 
     /// </summary> 
     /// <param name="ipRange"></param> 
     /// <returns></returns> 
     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; 
     } 

     /// <summary> 
     /// Parse IP-range string "12.15-16.1-30.10-255" 
     /// </summary> 
     /// <param name="ipRange"></param> 
     /// <returns></returns> 
     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; 
    } 
} 
11

Überprüfen Sie das Snippet here. Halten Sie die Credits an Ort und Stelle, wenn Sie dies bitte verwenden.

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<string> 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; 
     } 
    } 
} 
3

Ich denke, das sollte es tun.

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<IPAddress> 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 }); 
       } 
      } 
     } 
    } 
} 
2

Ich bin zu spät, um das Spiel, aber Ihre Frage wurde doppelt erwähnt, so dass ich nur hinzufügen, die Antwort hier. Mit Hilfe der IPAddressRange Bibliothek können Sie Ihre IPs wie das aufzählen:

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); 
} 

Die Bibliothek unterstützt auch CIDR Notation und Bereich Strings

Verwandte Themen