如何在C#中将IP范围转换为Cidr?

如何在C#中将IP范围转换为Cidr?,c#,ip,cidr,C#,Ip,Cidr,有很多将CIDR转换为ip范围的示例。但我想知道如何使用开始/结束ip地址生成C#中的某个cidr 例如: 我有起始ip地址(192.168.0.1)和结束ip地址(192.168.0.254)。因此,使用这两个地址生成cidr列表{192.168.0.0/31192.168.0.2/32}。是否有C代码示例?很难确定此处询问的确切内容(您给出的CIDR列表似乎与给定的输入地址不一致),但是以下代码将允许您找到包含指定起始和结束地址的最小单个CIDR 您需要首先将起始和结束IP地址转换为32位整

有很多将CIDR转换为ip范围的示例。但我想知道如何使用开始/结束ip地址生成C#中的某个cidr

例如:
我有起始ip地址(192.168.0.1)和结束ip地址(192.168.0.254)。因此,使用这两个地址生成cidr列表{192.168.0.0/31192.168.0.2/32}。是否有C代码示例?

很难确定此处询问的确切内容(您给出的CIDR列表似乎与给定的输入地址不一致),但是以下代码将允许您找到包含指定起始和结束地址的最小单个CIDR

您需要首先将起始和结束IP地址转换为32位整数(例如,192.168.0.1变为0xc0a80001),然后应用以下算法:

var startAddr = 0xc0a80001; // 192.168.0.1
var endAddr = 0xc0a800fe;   // 192.168.0.254

// Determine all bits that are different between the two IPs
var diffs = startAddr ^ endAddr;

// Now count the number of consecutive zero bits starting at the most significant
var bits = 32;
var mask = 0;
while (diffs != 0)
{
    // We keep shifting diffs right until it's zero (i.e. we've shifted all the non-zero bits off)
    diffs >>= 1;
    // Every time we shift, that's one fewer consecutive zero bits in the prefix
    bits--;
    // Accumulate a mask which will have zeros in the consecutive zeros of the prefix and ones elsewhere
    mask = (mask << 1) | 1;
}

// Construct the root of the range by inverting the mask and ANDing it with the start address
var root = startAddr & ~mask;
// Finally, output the range
Console.WriteLine("{0}.{1}.{2}.{3}/{4}", root >> 24, (root >> 16) & 0xff, (root >> 8) & 0xff, root & 0xff, bits);

我发现了这个,并将其转换为C#,它现在正在工作。

CIDR
类使用静态方法将IP范围拆分为最小的不相交的
CIDR
范围集,这些范围完全覆盖原始IP范围

拆分方法(处理实际工作的大整数的“真实”方法,以及用于IP地址和CIDR创建的包装)位于底部

foreach一起使用(IPRangeToCidr.CIDR.split中的IPRangeToCidr.CIDR c(第一个、最后一个))…

引用中需要System.Numerics.dll

使用系统;
使用系统数字;
Net系统;
使用System.Net.Sockets;
使用System.Collections.Generic;
命名空间IPRangeToCidr{
公共结构CIDR{
专用IP地址;
专用uint网络长度,位;
公共CIDR(IP地址地址,uint网络长度){
this.address=地址;
this.network_length=网络长度;
this.bits=AddressFamilyBits(address.AddressFamily);
if(网络长度>位){
抛出新的ArgumentException(“无效的网络长度”+网络长度+”,表示“+地址.AddressFamily”);
}
}
公共IP地址网络地址{
获取{返回地址;}
}
公共IP地址{

get{return IPAddressAdd(address,(new biginger(1)我建议使用IPNetwork库。 从版本2开始,它还支持IPv4和IPv6

Supernet

  IPNetwork network = IPNetwork.Parse("192.168.0.1");
  IPNetwork network2 = IPNetwork.Parse("192.168.0.254");

  IPNetwork ipnetwork = IPNetwork.Supernet(network, network2);

  Console.WriteLine("Network : {0}", ipnetwork.Network);
  Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
  Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
  Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
  Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
  Console.WriteLine("Usable : {0}", ipnetwork.Usable);
  Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);
输出

Network : 192.168.0.0
Netmask : 255.255.255.0
Broadcast : 192.168.0.255
FirstUsable : 192.168.0.1
LastUsable : 192.168.0.254
Usable : 254
Cidr : 24
玩得开心!

亡灵巫术。
不,没有,我不明白为什么人们总是投错误的答案

以下是IP范围到CIDR的代码,反之亦然:

// https://dev.maxmind.com/geoip/
// https://stackoverflow.com/questions/461742/how-to-convert-an-ipv4-address-into-a-integer-in-c
public static string IPrange2CIDR(string ip1, string ip2)
{
    uint startAddr = IP2num(ip1);
    uint endAddr = IP2num(ip2);

    // uint startAddr = 0xc0a80001; // 192.168.0.1
    // uint endAddr = 0xc0a800fe;   // 192.168.0.254
    // uint startAddr = System.BitConverter.ToUInt32(System.Net.IPAddress.Parse(ip1).GetAddressBytes(), 0);
    // uint endAddr = System.BitConverter.ToUInt32(System.Net.IPAddress.Parse(ip2).GetAddressBytes(), 0);

    if (startAddr > endAddr)
    {
        uint temp = startAddr;
        startAddr = endAddr;
        endAddr = temp;
    }

    // uint diff = endAddr - startAddr -1;
    // int bits =  32 - (int)System.Math.Ceiling(System.Math.Log10(diff) / System.Math.Log10(2));
    // return ip1 + "/" + bits;

    uint diffs = startAddr ^ endAddr;

    // Now count the number of consecutive zero bits starting at the most significant
    int bits = 32;
    // int mask = 0;

    // We keep shifting diffs right until it's zero (i.e. we've shifted all the non-zero bits off)
    while (diffs != 0)
    {
        diffs >>= 1;
        bits--; // Every time we shift, that's one fewer consecutive zero bits in the prefix
        // Accumulate a mask which will have zeros in the consecutive zeros of the prefix and ones elsewhere
        // mask = (mask << 1) | 1;
    }

    string res = ip1 + "/" + bits;
    System.Console.WriteLine(res);
    return res;
}




// https://www.digitalocean.com/community/tutorials/understanding-ip-addresses-subnets-and-cidr-notation-for-networking
public static void CIDR2IP(string IP)
{   
    string[] parts = IP.Split('.', '/');

    uint ipnum = (System.Convert.ToUInt32(parts[0]) << 24) |
        (System.Convert.ToUInt32(parts[1]) << 16) |
        (System.Convert.ToUInt32(parts[2]) << 8) |
        System.Convert.ToUInt32(parts[3]);

    int maskbits = System.Convert.ToInt32(parts[4]);
    uint mask = 0xffffffff;
    mask <<= (32 - maskbits);

    uint ipstart = ipnum & mask;
    uint ipend = ipnum | (mask ^ 0xffffffff);

    string fromRange = string.Format("{0}.{1}.{2}.{3}", ipstart >> 24, (ipstart >> 16) & 0xff, (ipstart >> 8) & 0xff, ipstart & 0xff);
    string toRange = string.Format("{0}.{1}.{2}.{3}", ipend >> 24, (ipend >> 16) & 0xff, (ipend >> 8) & 0xff, ipend & 0xff);

    System.Console.WriteLine(fromRange + " - " + toRange);
}



public static uint IP2num(string ip)
{
    string[] nums = ip.Split('.');
    uint first = System.UInt32.Parse(nums[0]);
    uint second = System.UInt32.Parse(nums[1]);
    uint third = System.UInt32.Parse(nums[2]);
    uint fourth = System.UInt32.Parse(nums[3]);

    return (first << 24) | (second << 16) | (third << 8) | (fourth);
}

public static void Test()
{
    string IP = "5.39.40.96/27";
    // IP = "88.84.128.0/19";
    CIDR2IP(IP);

    // IPrange2CIDR("88.84.128.0", "88.84.159.255");
    IPrange2CIDR("5.39.40.96", "5.39.40.127");

    System.Console.WriteLine(System.Environment.NewLine);
    System.Console.WriteLine(" --- Press any key to continue --- ");
    System.Console.ReadKey();
}
//https://dev.maxmind.com/geoip/
// https://stackoverflow.com/questions/461742/how-to-convert-an-ipv4-address-into-a-integer-in-c
公共静态字符串IPrange2CIDR(字符串ip1,字符串ip2)
{
uint STARTADR=IP2num(ip1);
uint endAddr=IP2num(ip2);
//uint STARTADR=0xc0a80001;//192.168.0.1
//uint endAddr=0xc0a800fe;//192.168.0.254
//uint startAddr=System.BitConverter.ToUInt32(System.Net.IPAddress.Parse(ip1.GetAddressBytes(),0);
//uint endAddr=System.BitConverter.ToUInt32(System.Net.IPAddress.Parse(ip2.GetAddressBytes(),0);
如果(开始地址>结束地址)
{
uint温度=开始温度;
startAddr=endAddr;
endAddr=温度;
}
//uint diff=endAddr-startAddr-1;
//int位=32-(int)System.Math.天花(System.Math.Log10(diff)/System.Math.Log10(2));
//返回ip1+“/”+位;
uint diffs=起始地址^endAddr;
//现在计算从最高有效位开始的连续零位数
整数位=32;
//int-mask=0;
//我们一直将差分向右移位,直到它为零(即,我们已将所有非零位移位)
而(差异!=0)
{
差值>>=1;
位--;//每次移位,前缀中的连续零位就会减少一位
//累积一个掩码,该掩码将在前缀的连续零中包含零,在其他位置包含一
//掩码=(掩码8)和0xff,ipstart和0xff);
string toRange=string.Format(“{0}.{1}.{2}.{3}”,ipend>>24,(ipend>>16)和0xff,(ipend>>8)和0xff,ipend和0xff);
系统控制台写入线(fromRange+“-”+toRange);
}
公共静态单元IP2num(字符串ip)
{
字符串[]nums=ip.Split('.');
uint first=System.UInt32.Parse(nums[0]);
uint second=System.UInt32.Parse(nums[1]);
uintthird=System.UInt32.Parse(nums[2]);
uint-fourth=System.UInt32.Parse(nums[3]);

返回(首先,请展示一些源代码……您尝试了什么?什么不起作用?这将计算包含两个给定IPv4地址的最小CIDR块,但我认为问题是关于完全覆盖该范围的CIDR列表。@Stefan由于示例中的输出,很难确定OP想要什么该选项似乎与给定的开始/结束地址不符。由于OP自己的答案(据推测)在一天后发布了所需的输出,在许多人认为我的答案足够有用,可以追加投票后,我将其保留原样。这似乎不值得(我假设)你投了反对票,但每个人都有自己的。嗯。编辑你的答案,这样你就可以清楚地解释这个问题了。阅读源代码以了解它的实际作用,这很烦人。@Stefan我编辑了答案,以澄清代码的意图。希望现在更清楚。提供转换后的c会更有帮助ode,因为他在C#中询问代码。该代码可以很好地生成IP范围的CIDR。这是正确的答案。@Steven Wolfe:WTF?问题是如何将IP范围转换为CIDR,而不是CIDR转换为IP范围,因此这不是正确的答案…@Stefanstieger是的,该类还包含提取第一个IP范围的代码(
NetworkAddress
)和CIDR范围的最后一个地址,但示例
split
的“main”函数会将IP范围转换为CIDR块列表。您实际阅读了描述吗
// https://dev.maxmind.com/geoip/
// https://stackoverflow.com/questions/461742/how-to-convert-an-ipv4-address-into-a-integer-in-c
public static string IPrange2CIDR(string ip1, string ip2)
{
    uint startAddr = IP2num(ip1);
    uint endAddr = IP2num(ip2);

    // uint startAddr = 0xc0a80001; // 192.168.0.1
    // uint endAddr = 0xc0a800fe;   // 192.168.0.254
    // uint startAddr = System.BitConverter.ToUInt32(System.Net.IPAddress.Parse(ip1).GetAddressBytes(), 0);
    // uint endAddr = System.BitConverter.ToUInt32(System.Net.IPAddress.Parse(ip2).GetAddressBytes(), 0);

    if (startAddr > endAddr)
    {
        uint temp = startAddr;
        startAddr = endAddr;
        endAddr = temp;
    }

    // uint diff = endAddr - startAddr -1;
    // int bits =  32 - (int)System.Math.Ceiling(System.Math.Log10(diff) / System.Math.Log10(2));
    // return ip1 + "/" + bits;

    uint diffs = startAddr ^ endAddr;

    // Now count the number of consecutive zero bits starting at the most significant
    int bits = 32;
    // int mask = 0;

    // We keep shifting diffs right until it's zero (i.e. we've shifted all the non-zero bits off)
    while (diffs != 0)
    {
        diffs >>= 1;
        bits--; // Every time we shift, that's one fewer consecutive zero bits in the prefix
        // Accumulate a mask which will have zeros in the consecutive zeros of the prefix and ones elsewhere
        // mask = (mask << 1) | 1;
    }

    string res = ip1 + "/" + bits;
    System.Console.WriteLine(res);
    return res;
}




// https://www.digitalocean.com/community/tutorials/understanding-ip-addresses-subnets-and-cidr-notation-for-networking
public static void CIDR2IP(string IP)
{   
    string[] parts = IP.Split('.', '/');

    uint ipnum = (System.Convert.ToUInt32(parts[0]) << 24) |
        (System.Convert.ToUInt32(parts[1]) << 16) |
        (System.Convert.ToUInt32(parts[2]) << 8) |
        System.Convert.ToUInt32(parts[3]);

    int maskbits = System.Convert.ToInt32(parts[4]);
    uint mask = 0xffffffff;
    mask <<= (32 - maskbits);

    uint ipstart = ipnum & mask;
    uint ipend = ipnum | (mask ^ 0xffffffff);

    string fromRange = string.Format("{0}.{1}.{2}.{3}", ipstart >> 24, (ipstart >> 16) & 0xff, (ipstart >> 8) & 0xff, ipstart & 0xff);
    string toRange = string.Format("{0}.{1}.{2}.{3}", ipend >> 24, (ipend >> 16) & 0xff, (ipend >> 8) & 0xff, ipend & 0xff);

    System.Console.WriteLine(fromRange + " - " + toRange);
}



public static uint IP2num(string ip)
{
    string[] nums = ip.Split('.');
    uint first = System.UInt32.Parse(nums[0]);
    uint second = System.UInt32.Parse(nums[1]);
    uint third = System.UInt32.Parse(nums[2]);
    uint fourth = System.UInt32.Parse(nums[3]);

    return (first << 24) | (second << 16) | (third << 8) | (fourth);
}

public static void Test()
{
    string IP = "5.39.40.96/27";
    // IP = "88.84.128.0/19";
    CIDR2IP(IP);

    // IPrange2CIDR("88.84.128.0", "88.84.159.255");
    IPrange2CIDR("5.39.40.96", "5.39.40.127");

    System.Console.WriteLine(System.Environment.NewLine);
    System.Console.WriteLine(" --- Press any key to continue --- ");
    System.Console.ReadKey();
}