8

如果我有一个子网掩码255.255.255.0和一个 IP 地址192.168.1.5,是否有一种简单的方法可以确定该子网内所有可能的 IP 地址?

在这种情况下:

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
...
...
192.168.1.252
192.168.1.253
192.168.1.254
192.168.1.255

到目前为止,我发现的只是重载的 .net 库。没有任何本地方法可以使用默认命名空间解决这个问题吗?

4

5 回答 5

13

10 分钟的编码,未经过全面测试:

class IPSegment {

    private UInt32 _ip;
    private UInt32 _mask;

    public IPSegment(string ip, string mask) {
        _ip = ip.ParseIp();
        _mask = mask.ParseIp();
    }

    public UInt32 NumberOfHosts {
        get { return ~_mask+1; }
    }

    public UInt32 NetworkAddress {
        get { return _ip & _mask; }
    }

    public UInt32 BroadcastAddress {
        get { return NetworkAddress + ~_mask; }
    }

    public IEnumerable<UInt32> Hosts(){
        for (var host = NetworkAddress+1; host < BroadcastAddress; host++) {
            yield return  host;
        }
    }

}

public static class IpHelpers {
    public static string ToIpString(this UInt32 value) {
        var bitmask = 0xff000000;
        var parts = new string[4];
        for (var i = 0; i < 4; i++) {
            var masked = (value & bitmask) >> ((3-i)*8);
            bitmask >>= 8;
            parts[i] = masked.ToString(CultureInfo.InvariantCulture);
        }
        return String.Join(".", parts);
    }

    public static UInt32 ParseIp(this string ipAddress) {
        var splitted = ipAddress.Split('.');
        UInt32 ip = 0;
        for (var i = 0; i < 4; i++) {
            ip = (ip << 8) + UInt32.Parse(splitted[i]);
        }
        return ip;
    }
}

用法:

    static void Main(string[] args) {

        IPSegment ip = new IPSegment("192.168.1.1","255.255.255.248");

        Console.WriteLine(ip.NumberOfHosts);
        Console.WriteLine(ip.NetworkAddress.ToIpString());
        Console.WriteLine(ip.BroadcastAddress.ToIpString());

        Console.WriteLine("===");
        foreach (var host in ip.Hosts()) {
            Console.WriteLine(host.ToIpString());
        }
        Console.ReadLine();

    }
于 2013-01-14T22:38:25.267 回答
9

要确定地址范围,请执行以下步骤:

1)获取您的子网掩码(此处为 255.255.255.0)并将其转换为二进制:

11111111.11111111.11111111.00000000

 (  8    +    8   +   8    +    0    = 24 ->  So you can write your ip adresse like this : 192.168.1.x/24 because you are in a /24 network)

2)您在 /24 网络中有 256-2=254 个可用的主机 IP 地址(一个用于网络地址(您范围内的第一个),另一个用于广播地址(您范围内的最后一个)) .

3) 要获取您的范围,只需获取您的网络地址(根据您的子网掩码的第一个 ip 地址)并获取接下来的 255 个 IP 地址,您将拥有您的范围。

您的网络地址:

在二进制中,最后一个八位字节必须为 null :

xxxxxxxx.xxxxxxxx.xxxxxxxx.00000000

您的广播地址:

在二进制中,最后一个八位字节必须等于 1:

xxxxxxxx.xxxxxxxx.xxxxxxxx.11111111

这里你的 ip 地址是 192.168.1.5。在二进制中,我们得到:

11000000.10101000.00000000.00000101
  1. 您的网络地址:11000000.10101000.00000000.00000000 <-> 192.168.1.0
  2. 你的广播地址:11000000.10101000.000000000.11111111 <-> 192.168.1.255
  3. 第一个可用IP地址:192.168.1.1

  4. 最后可用IP地址:192.168.1.254

希望你喜欢阅读糟糕的英语。如果你有任何问题,请告诉我,洛里斯

于 2013-01-14T21:52:46.037 回答
1

是的,将所有内容都转换为 32 位表示(假设 IPv4)。如果您的掩码是 M 而 ip 是 IP,那么您的 ip 范围是 (M&IP)+1,(M&IP)+2,...,(M&IP)+(~M)-1。其中 & 是按位与,而 ~ 是按位非。

要将事物转换为 32 位表示,ip abcd 中的每个点都是一个 8 位数字。

于 2013-01-14T21:33:47.977 回答
1

要使用,只需:

string[] range GetIpRange("100.68.18.218", "255.255.255.252",true)`;

最后一个参数true是过滤第一个和最后一个IP
来得到完整的答案,把它设置为false

它将返回第一个和最后一个可用的 IP。

所有代码解释如下:


/// <summary>
/// IPAddress to UInteger 
/// </summary>
/// <param name="ipAddress"></param>
/// <returns></returns>
public static uint IPToUInt(this string ipAddress)
{
    if (string.IsNullOrEmpty(ipAddress))
        return 0;

    if (IPAddress.TryParse(ipAddress, out IPAddress ip))
    {
        var bytes = ip.GetAddressBytes();
        Array.Reverse(bytes);
        return BitConverter.ToUInt32(bytes, 0);
    }
    else
        return 0;

}

/// <summary>
/// IP in Uinteger to string
/// </summary>
/// <param name="ipUInt"></param>
/// <returns></returns>
public static string IPToString(this uint ipUInt)
{
    return ToIPAddress(ipUInt).ToString();
}


/// <summary>
/// IP in Uinteger to IPAddress
/// </summary>
/// <param name="ipUInt"></param>
/// <returns></returns>
public static IPAddress ToIPAddress(this uint ipUInt)
{
    var bytes = BitConverter.GetBytes(ipUInt);
    Array.Reverse(bytes);
    return new IPAddress(bytes);
}

/// <summary>
/// First and Last IPv4 from IP + Mask
/// </summary>
/// <param name="ipv4"></param>
/// <param name="mask">Accepts CIDR or IP. Example 255.255.255.0 or 24</param>
/// <param name="filterUsable">Removes not usable IPs from Range</param>
/// <returns></returns>
/// <remarks>
/// If ´filterUsable=false´ first IP is not usable and last is reserved for broadcast.
/// </remarks>
public static string[] GetIpRange(string ipv4, string mask, bool filterUsable)
{
    uint[] uiIpRange = GetIpUintRange(ipv4, mask, filterUsable);

    return Array.ConvertAll(uiIpRange, x => IPToString(x));
}

/// <summary>
/// First and Last IPv4 + Mask. 
/// </summary>
/// <param name="ipv4"></param>
/// <param name="mask">Accepts CIDR or IP. Example 255.255.255.0 or 24</param>
/// <param name="filterUsable">Removes not usable IPs from Range</param>
/// <returns></returns>
/// <remarks>
/// First IP is not usable and last is reserverd for broadcast.
/// Can use all IPs in between
/// </remarks>
public static uint[] GetIpUintRange(string ipv4, string mask, bool filterUsable)
{
    uint sub;
    //check if mask is CIDR Notation
    if (mask.Contains(".")) {
        sub = IPToUInt(mask);
    }
    else
    {
        sub = ~(0xffffffff >> Convert.ToInt32(mask));
    }

    uint ip2 = IPToUInt(ipv4);
 

    uint first = ip2 & sub;
    uint last = first | (0xffffffff & ~sub);

    if (filterUsable)
    {
        first += 1;
        last -= 1; 
    }

    return new uint[] { first, last };
}

于 2021-09-24T16:10:54.430 回答
0

好决定。不要为此使用额外的库。这很简单。我就是这样做的:

public static uint[] GetIpRange(string ip, IPAddress subnet)
{
    uint ip2 = Utils.IPv4ToUInt(ip);
    uint sub = Utils.IPv4ToUInt(subnet);

    uint first = ip2 & sub;
    uint last = first | (0xffffffff & ~sub);

    return new uint[] { first, last };
}

注意:
您需要做更多的工作将 IP 转换为 uint 并返回(应该很容易)。然后,您可以在firstlast之间使用简单的 for 循环迭代所有 IP 。

像这样的东西(未经测试):

byte[] bytes = subnet.GetAddressBytes();
uint sub = (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);

IPAddress ip1 = IPAddress.Parse(ip);
bytes = ip1.GetAddressBytes();
uint ip2 = (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
于 2016-09-21T08:59:07.233 回答