2015-12-08 2 views
0

Имеются сообщения, связанные с преобразованием обозначений CIDR в диапазоны IP. Мне нужно обратное. Мне нужно скомпилировать много IP-адресов в CIDR-запись, если это возможно.C# IP-список для возможной записи CIDR?

ввода Пример:

192.168.0.0 
192.168.0.1 
.. 
.. 
192.168.0.255 
192.168.2.4 
192.168.3.8 

Выход Пример:

192.168.0/24 
192.168.2.4 
192.168.3.8 

Так, 192.168.2.4 и 192.168.3.8 не может представлено CIDR нотации, это может быть список, как это было.

Я знаю, что это трудно. Потому что CIDR нотация имеет разный размер блоков. Но по крайней мере, как я могу сжать свой список с блоком C (256 IP)?

Я постараюсь сделать это с помощью C# linq.

ответ

0

Сложно обойтись без кодирования. Вот моя попытка написать CidrCompressor. Вызовите Add() для каждого IP-адреса, а затем получите сжатый список, используя свойство IpList.

public class CidrCompressor 
{  
    private readonly Regex _subnetRegex = new Regex(@"^(?<net>\d+\.\d+\.\d+)\.0$", RegexOptions.Compiled); 
    private Regex _currentNetRegex; 
    private string _currentNet; 
    private int _lastSubIp; 

    private List<string> _ipList = new List<string>(); 

    private void AddReceivedInSubnet() 
    { 
     for (var i = 0; i < _lastSubIp; ++i) 
     { 
      _ipList.Add(string.Format("{0}.{1}", _currentNet, i)); 
     } 
     _currentNetRegex = null; 
    } 

    public void Add(string ip) 
    { 
     var m = _subnetRegex.Match(ip); 
     if (m.Success) 
     { 
      // Matches *.0 
      // Start matching subnet 
      _currentNet = m.Groups["net"].Value; 
      _currentNetRegex = new Regex(string.Format(@"^{0}\.(?<subIp>\d+)$", _currentNet));   
      _lastSubIp = 0; 
     } 
     else if (_currentNetRegex != null) 
     { 
      // Currently matching a subnet 
      m = _currentNetRegex.Match(ip); 

      if (m.Success) 
      { 
       var subIp = int.Parse(m.Groups["subIp"].Value); 

       if (subIp == _lastSubIp + 1) 
       { 
        // See if we have received a full subnet 
        if (subIp == 255) 
        { 
         _ipList.Add(_currentNet + "/24"); 
         _currentNetRegex = null;      
        } 
        else 
        { 
         _lastSubIp = subIp; 
        } 
       } 
       else 
       { 
        // Not continuous so add indivudial IPs 
        AddReceivedInSubnet(); 
        Add(ip); 
       } 
      } 
      else 
      { 
       // Received IP in different net before .255 
       // Add all IPs received 
       AddReceivedInSubnet(); 

       // Process ip we received 
       Add(ip); 
      } 
     } 
     else 
     { 
      _ipList.Add(ip); 
     } 
    } 

    public IEnumerable<string> IpList 
    { 
     get 
     { 
      return _ipList; 
     } 
    } 
} 
+0

Thx Krister, но ваше решение кажется сложным. Я напишу свое решение ниже. – akdora

0

я найти решение для C блок CIDR нотации, но это для ТОЛЬКО C блок. не для всех блоков.

public static List<string> IpListToCIDR(List<string> ipList) 
    { 
     //Suanda sadece C blok icin yazilmistir. Ileride gelistirilebilir 
     //result list 
     List<string> compressedList = new List<string>(); 

     //group ip addresses 
     var cidrList = ipList.GroupBy(o => new 
          { 
           GrpKey = o.Substring(0, o.LastIndexOf('.')) 
          }) 
          .Select(g => new 
          { 
           IpSubnet = g.Key.GrpKey, 
           Count = g.Count() 
          }) 
          .Where(m => m.Count >= 255) 
          .ToList(); 
     //exclude grouped list 
     var excludeList = (from a in ipList 
          join c in cidrList on a.Substring(0, a.LastIndexOf('.')) equals c.IpSubnet 
          select a).ToList(); 

     //add C block CIDR list 
     compressedList.AddRange(cidrList.Select(m => m.IpSubnet + ".0/24").ToList()); 
     //add rest of them 
     compressedList.AddRange(ipList.Where(m=> !excludeList.Contains(m)).ToList()); 

     return compressedList; 
    } 
Смежные вопросы