如何在C#List中存储IP地址列表,使其也可以搜索到子网?

GrZ*_*eCh 6 c# comparison ip-address subnet

我应该如何正确地存储IP地址列表与地址作为子网,使其可搜索?

有两个例子:

  1. 我有IP地址1.2.3.4,在我的C#List中有1.2.3.4条目,所以这里我们没有问题.

  2. 我有IP地址3.4.5.6,在我的C#列表中我有子网3.4.0.0/24.这是我的问题.

如何在List中存储IP子网以涵盖第二个示例?

谢谢

Ant*_*nes 4

在本答案的最后,您将找到表示 IPV4 地址的结构的完整实现。

这是非常简单的用法示例:-

List<IPV4Address> list = new List<IPV4Address>();
list.Add(IPV4Address.FromString("3.4.0.0", 24));
var x = IPV4Address.FromString("3.4.0.6");
foreach (var addr in list.Where(a => a.Contains(x)))
  Console.WriteLine(addr);
Run Code Online (Sandbox Code Playgroud)

由于在 3.4.0.0/24 子网中找到了 3.4.0.6,因此控制台中会显示值“3.4.0.0/255.255.255.0”。假设list充满了各种子网并且x可以包含任何地址,那么:-

var result = list.Where(a => a.Contains(x))
    .OrderByDescending(a => a.Mask)
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

将选择包含 的最具体的子网x

public struct IPV4Address
{
  private UInt32 _Value;
  private UInt32 _Mask;

  public UInt32 Value
  {
    get { return _Value; }
    private set { _Value = value; }
  }

  public UInt32 Mask
  {
    get { return _Mask; }
    private set { _Mask = value; }
  }

  public static IPV4Address FromString(string address)
  {
    return FromString(address, 32);
  }

  public static IPV4Address FromString(string address, int maskLength)
  {
    string[] parts = address.Split('.');
    UInt32 value = ((UInt32.Parse(parts[0]) << 24) +
      ((UInt32.Parse(parts[1])) << 16) +
      ((UInt32.Parse(parts[2])) << 8) +
      UInt32.Parse(parts[3]));

    return new IPV4Address(value, maskLength);
  }

  public IPV4Address(UInt32 value)
  {
    _Value = value;
    _Mask = int.MaxValue;
  }

  public IPV4Address(UInt32 value, int maskLength)
  {
    if (maskLength < 0 || maskLength > 32)
      throw new ArgumentOutOfRangeException("maskLength", "Must be 0 to 32");

    _Value = value;
    if (maskLength == 32)
      _Mask = UInt32.MaxValue;
    else
      _Mask = ~(UInt32)((1 << (32 - maskLength))-1);

    if ((_Value & _Mask) != _Value)
      throw new ArgumentException("Address value must be contained in mask");
  }

  public bool Contains(IPV4Address address)
  {
    if ((Mask & address.Mask) == Mask)
    {
      return (address.Value & Mask) == Value;
    }
    return false;
  }

  public override string ToString()
  {
    string result = String.Format("{0}.{1}.{2}.{3}", (_Value >> 24), 
      (_Value >> 16) & 0xFF, 
      (_Value >> 8) & 0xFF, 
      _Value & 0xFF);

    if (_Mask != UInt32.MaxValue)
      result += "/" + String.Format("{0}.{1}.{2}.{3}", (_Mask >> 24),
      (_Mask >> 16) & 0xFF,
      (_Mask >> 8) & 0xFF,
      _Mask & 0xFF);

    return result;
  }
}
Run Code Online (Sandbox Code Playgroud)