簡體   English   中英

根據給定的整數生成連續的 IPv4 地址

[英]Generate consecutive IPv4 addresses based on a given integer

/// <summary>
    /// Create IP part of the client information payload.
    /// </summary>
    /// <param name="index">Index of the current client being generated.</param>
    /// <returns>Simulated client IP address.</returns>
    private string CreateClientIp(UInt32 index)
    {
        index = (index << 2) + 3;
        return $"192.{(index >> 16) & 0xFF}.{(index >> 8) & 0xFF}.{index & 0xFF}";
    }

下面的方法是從 192.0.0.3 開始生成 IP,增量為 3。我希望我的第一個地址是 192.0.0.2(以避免網絡地址以及通常用於 GW 的第一個地址),然后增加下一個地址由一個。 對此有何想法? 謝謝!

我認為最簡單的方法是使用 IPAddress 並操作用於創建它們的字節。 如果您需要以字符串形式返回的 IP 地址,請在返回的 IP 地址上使用 ToString()。

    static void Main(string[] _)
    {
        var address = IPAddress.Parse("192.168.0.2");

        foreach (var ip in GetTestAddresses(address, 300))
        {
            Console.WriteLine(ip);
        }
    }

    public static IEnumerable<IPAddress> GetTestAddresses(IPAddress start, int count)
    {
        var bytes = start.GetAddressBytes();

        for (int i = 0; i < count; ++i)
        {
            var part4 = bytes[^1];
            var part3 = bytes[^2];

            if (part4 < 255)
            {
                ++part4;
            }
            else if (part3 < 255)
            {
                part4 = 0;
                ++part3;
            }
            else
            {
                break;
            }

            bytes[^1] = part4;
            bytes[^2] = part3;

            yield return new IPAddress(bytes);
        }
    }

最好的結果是使用本機 C#/.Net IPv4 結構。 不幸的是,.Net 沒有很好的原生 IPv4 工具,或者至少我不知道它們。 System.Net.IPAddress ,但它試圖在同一個地方同時支持 IPv6 和 IPv4。 當一個簡單的 32 位值可以做到時,它迫使我們存儲 64 位加上一堆額外的標志。

如果做不到這一點,我們應該考慮uint值而不是字符串,至少對於較低級別的數學內容。 我確信有一個 NuGet 庫會有所幫助,但這很簡單,我可以把它放在這個答案中。

我也認為這是使用一些有趣的 linq 技術(例如迭代器和自定義運算符)的好地方(或至少有趣)。 我們可以制作一個簡單的序列,從給定的起點返回uint值並知道廣播地址:

public static uint MaskFromCidr(int cidr)
{
    //cidr is the number of 1's at the start of the result
    // So /24 is 11111111111111111111111100000000 is 255.255.255.0
    return uint.MaxValue << (32-cidr);
}

public static bool CheckMask(uint IP, uint mask)
{
    return (IP | mask) == uint.MaxValue;
}
    
public static bool CheckMask(uint IP, int cidr)
{
    return CheckMask(IP, MaskFromCidr(cidr));
}

public static IEnumerable<uint> IPSequence(uint start_address, int cidr = 24)
{
    uint mask = MaskFromCidr(cidr);
            
    while (!CheckMask(start_address, mask))
    {
        yield return start_address;
        start_address++;
    }
}

然后添加一個 linq 運算符和一個格式化函數以進行良好的度量:

public static IEnumerable<T> EveryNth<T>(this IEnumerable<T> items, int n)
{
    int i = 0;
    foreach(var item in items)
    {
        if (i % n == 0)
        {
            yield return item;
            i = 0; //for LARGE sequences, prevent int overflow
        }
        i++;
    }
}

public static string DottedQuadFromUInt(uint IP)
{   
    return $"{(IP >> 24) & 0xFF}.{(IP >> 16) & 0xFF}.{(IP >> 8) & 0xFF}.{IP & 0xFF}";
}

然后像這樣把它們綁在一起:

uint start = 3232235522; //192.168.0.2 https://www.vultr.com/resources/ipv4-converter/?ip_address=192.168.0.2
var addresses = IPSequence(start).EvernNth(3).Take(2).Select(DottedQuadFromUInt);
foreach(var address in addresses)
{
    Console.WriteLine(address);
}

請注意,我使用了192.168.0.2而不是192.0.0.2 后者是public-routable ,你不應該將它用於內部地址。

看到它在這里工作:


https://dotnetfiddle.net/Ho2rqg


這是避免地址以 255 結尾的更好代碼:

       public class IncrementIP
        {
            byte[] array = new byte[4];
            public IncrementIP(string IP)
            {
                array = IP.Split(new char[] { '.' }).Select(x => byte.Parse(x)).ToArray();
            }
            public string Increment()
            {
                int lsb = array[3] + 3;
                if (lsb <= 254)
                {
                    array[3] = (byte)lsb;
                }
                else
                {
                    array[3] = 2;
                    for (int i = 2; i >= 0; i--)
                    {
                        if (array[i] == 254)
                        {
                            array[i] = 0;
                        }
                        else
                        {
                            array[i] += 1;
                            break;
                        }
                    }
                }

                return string.Join(".", array);
            }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM