jsakamoto / ipaddressrange

.NET Class Library for range of IP address, both IPv4 and IPv6.
Mozilla Public License 2.0
368 stars 71 forks source link

Parse("10.0.0.1/1") #85

Open cnbohu opened 1 month ago

cnbohu commented 1 month ago
var ipRange = IPAddressRange.Parse("10.0.0.1/1") ;
int iCount = ipRange.AsEnumerable().Count(); 

iCount is '-2147483648' ?

jsakamoto commented 1 month ago

Hi @cnbohu ,

iCount is '-2147483648' ?

It is because the number of IP addresses is over the max range of the type of int, which caused overflow. In short, it represents int.MaxValue + 1.

If you cast the return value of the Count() extension method to the UInt32 type, like below, you will get the correct number of the IP addresses in that range.

var ipRange = IPAddressRange.Parse("10.0.0.1/1") ;
var count = (UInt32)ipRange.AsEnumerable().Count();

Happy Coding ;)

cnbohu commented 1 month ago

Thx! But, Other errors are encountered in IPv6 “2408:8220:332:39f0::/60”

var ipRange = IPAddressRange.Parse("2408:8220:332:39f0::/60");
BigInteger iIpCount = (BigInteger)ipRange.AsEnumerable().LongCount();

program is unresponsive ...

jsakamoto commented 1 month ago

Hi @cnbohu,

program is unresponsive ...

Becuase that program will count about 300,000,000,000,000,000,000 objects (!). If it takes one microsecond to count one address, it will take more than 9 million years to finish counting this number of addresses...!

Instead, use the following expression to get the number of the IPv6 addresses.

var count = (UInt128)System.Math.Pow(2, 128 - 60 /* <- the length of the bit mask */ );
cnbohu commented 1 month ago

It is possible, to add a properties or methods, not generate objects,only calculate the count.

public BigInteger Total
{
    get
    {
        int max = this.Begin.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128;
        var count = BigInteger.Pow(2, max - this._prefixLength);
        return count;
    }
}
jsakamoto commented 1 month ago

It is possible, to add a properties or methods, not generate objects,only calculate the count.

That's true! In fact, we already have a code like you mentioned to implement the ICollection<T> interface.

https://github.com/jsakamoto/ipaddressrange/blob/master/IPAddressRange/Internals/IPv4RangeOperator.cs#L42

int ICollection<IPAddress>.Count => (int)((this.End - this.Begin) + 1);

(Actually, the implementation above is more generic, simple, and fast than using the power of two.)

That's the reason why your code ipRange.AsEnumerable().Count() returns value immediately. The IEnumerable<T>.Count extension method uses the ICollection<T>.Count method directly if the target object implements ICollection<T> instead of enumerating each element.

But unfortunately, the return type of the ICollection<T>.Count method is int. So, currently, this approach doesn't resolve all cases, like your case.

So many people don't care about the number of addresses in a range, so we haven't exposed such a feature on the IPAddressRange so far. But if you hope it, we might consider exposing something like the UInt128 Count property on the IPAddressRange.

cnbohu commented 1 month ago

In my project, need to get CIDR total IPs ,estimate(total * tasks) to customize the execution of scheduled jobs.

Like this: 9.9.0.0/16 => 65536 IP x 4 tasks = 262144 queries

I write the method to calculation,now function completed.

Thank for your work & reply!Hope your features will be available in the future.