简体   繁体   中英

Calculate IP range by subnet mask

If I have a subnet mask eg 255.255.255.0 and an ip address 192.168.1.5 , is there an easy way to determine all the possible ip addresses within this subnet?

In this case:

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

All I found until now are heavy overloaded .net libraries. Isn't there any native way to solve this with the default namespaces?

10 minutes of coding, and NOT fully tested:

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

Usage:

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

    }

To determine the adress range follow these steps :

1) Take your subnet mask (here 255.255.255.0) and convert it in binary :

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) You have in a /24 network 256-2=254 usable ip adresses for host (one is for the network adress (the first in your range) and the other one is for the broadcast adress (the last in your range)).

3) To get your range simply get your network adress (the first ip adress according to your subnet mask) and get the next 255 ip addresses and you'll have your range.

Your network adress:

In binary the last octet has to be null :

xxxxxxxx.xxxxxxxx.xxxxxxxx.00000000

Your broadcast adress:

In binary the last octet has to be equal to 1:

xxxxxxxx.xxxxxxxx.xxxxxxxx.11111111

Here your ip adress is 192.168.1.5. In binary we get:

11000000.10101000.00000000.00000101
  1. Your network address: 11000000.10101000.00000000.00000000 <-> 192.168.1.0
  2. Your broadcast address: 11000000.10101000.000000000.11111111 <-> 192.168.1.255
  3. First usable ip address: 192.168.1.1

  4. Last usable ip address : 192.168.1.254

Hope you enjoyed reading bad english. Tell me if you have any question, Loris

yup, convert everything to 32-bit representation (assuming IPv4). if your mask is M and ip is IP, then your ip range is (M&IP)+1,(M&IP)+2,...,(M&IP)+(~M)-1. where & is bitwise AND and ~ is bitwise not.

to convert things to 32-bit representation, each spot in the ip abcd is an 8-bit number.

Good call. Don't use extra libraries for that. It's quite simple. This is how I do it:

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

Note:
You'll need to do some more work converting IPs to uint and back (should be easy enough). Then you can iterate all IPs with a simple for-loop between first and last .

Something like this (not tested):

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM