2010-11-13 31 views
17

Làm cách nào để lặp qua một loạt các địa chỉ IP do người dùng cung cấp?C#: Liệt kê các địa chỉ IP trong một phạm vi

Tôi linh hoạt theo định dạng, miễn là nó cho phép tất cả các phạm vi được chỉ định. Có lẽ một cái gì đó giống như 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 

Ví dụ, nếu người dùng nhập 192.0.2-3.1-254, tôi muốn biết làm thế nào để tạo ra một danh sách tất cả các địa chỉ IP hợp lệ trong phạm vi này để tôi có thể lặp qua chúng .

Trả lời

19

Ví dụ:

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

Khám phá đoạn mã here. Giữ các khoản tín dụng tại chỗ nếu bạn sử dụng điều này xin vui lòng.

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

Tôi nghĩ rằng điều này sẽ làm điều đó.

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

Tôi đến cuối trò chơi, nhưng câu hỏi của bạn đã được đề cập trùng lặp, vì vậy tôi chỉ thêm câu trả lời ở đây. Sử dụng thư viện IPAddressRange, bạn có thể liệt kê IP của bạn như thế:

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

Thư viện cũng hỗ trợ CIDR ký hiệu và phạm vi chuỗi

Các vấn đề liên quan