如何在C#中将CIDR转换为网络和IP地址范围?

17
我已经找了很多关于将CIDR表示法(72.20.10.0/24)的网络转换为IP地址范围的C#代码,但没有什么好结果。虽然在stackoverlow上有一些与CIDR有关的主题,但似乎没有任何C#代码并且涵盖我所需的内容。因此,我决定自己编写代码,并且在这个版本中不想让代码依赖于System.Net进行任何转换。
也许对某些人有帮助。
参考: 从网络位数转换到子网掩码的最佳方法是什么? http://www.laffeycomputer.com/whatmask.html的"Whatmask" C代码
用法:
uint startIP, endIP;  
Network2IpRange("72.20.10.0/24", out startIP, out endIP); 

代码假定所有内容都是32位。
static void Network2IpRange(string sNetwork, out uint startIP, out uint endIP)
{           
    uint ip,        /* ip address */
        mask,       /* subnet mask */               
        broadcast,  /* Broadcast address */
        network;    /* Network address */

    int bits;               

    string[] elements = sNetwork.Split(new Char[] { '/' });         

    ip = IP2Int(elements[0]);
    bits = Convert.ToInt32(elements[1]);

    mask = ~(0xffffffff >> bits);

    network = ip & mask;
    broadcast = network + ~mask;

    usableIps = (bits >30)?0:(broadcast - network - 1); 

    if (usableIps <= 0)
    {
        startIP = endIP = 0; 
    }
    else
    {
        startIP = network + 1;              
        endIP = broadcast - 1;
    }
}

public static uint IP2Int(string IPNumber)
{
    uint ip = 0;
    string[] elements = IPNumber.Split(new Char[] { '.' });
    if (elements.Length==4)
    {
        ip  = Convert.ToUInt32(elements[0])<<24;
        ip += Convert.ToUInt32(elements[1])<<16;
        ip += Convert.ToUInt32(elements[2])<<8;
        ip += Convert.ToUInt32(elements[3]);
    }
    return ip;
}

欢迎提交您的改进。

4个回答

23

我建议使用来自Github的C# IPNetwork类。

string net = "192.168.168.100/24";
IPNetwork ipnetwork = IPNetwork.Parse(net);

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.168.0
Netmask : 255.255.255.0
Broadcast : 192.168.168.255
FirstUsable : 192.168.168.1
LastUsable : 192.168.168.254
Usable : 254 
Cidr : 24

玩得开心。


10

以下是针对您的示例 72.20.10.0/24 的操作步骤:

网络地址72.20.10.0
子网掩码~((1 << (32-24)) - 1) //或者
子网掩码~(0xFFFFFFFF >> 24)

  • 得到的结果是0xFFFFFF00

起始IP地址为 -- (网络地址 & 子网掩码);

  • 得到的结果是72.20.10.0 & 0xFFFFFF00

结束IP地址为 -- ((网络地址 & 子网掩码) | ~子网掩码);

  • 得到的结果是(72.20.10.0 & 0xFFFFFF00) | 0x000000FF

这将得到的IP地址范围为72.20.10.0 -- 72.20.10.255


5
对于一个 network/maskBits,步骤如下:
通过以下两种方式之一计算出 mask
mask = ~((1 << (32 - maskBits)) - 1) // or,
mask = ~(0xFFFFFFFF >> maskBits)

那么范围是:
StartIP = network 
EndIP   = network | ~mask

更准确地说,
StartIP = network & mask
EndIP   = (network & mask) | ~mask

在这里,

  • << 表示按位左移(不带循环)
  • & 表示按位与,
  • | 表示按位或,以及
  • ~ 表示按位取反。

1
maskBits 为 32 时,mask = ~(0xFFFFFFFF >> maskBits) 不会产生正确的值 - 值将为 0x0 而不是 0xFFFFFFFF。 - Colin Breame
实际上,我没有让这两种方法都起作用。~(0xFFFFFFFF >> 24) 返回的是 0.255.255.255 而不是 255.255.255.0。对我有用的是:0xFFFFFFFF >> -24 - cogumel0

3
这里是如何在T-SQL中将CIDR表示法转换为范围的方法,详见我的博客文章:http://bitmugger.blogspot.com/2011/02/how-to-convert-cidr-ip-address-to-range.html
先在SQL Server中预先创建此函数(来源于http://www.stardeveloper.com)。
CREATE FUNCTION [dbo].[ConvertIPToLong](@IP varchar(15))
RETURNS bigint
AS
BEGIN
    DECLARE @Long bigint
    SET @Long = CONVERT(bigint, PARSENAME(@IP, 4)) * 256 * 256 * 256 +
        CONVERT(bigint, PARSENAME(@IP, 3)) * 256 * 256 +
        CONVERT(bigint, PARSENAME(@IP, 2)) * 256 +
        CONVERT(bigint, PARSENAME(@IP, 1))

    RETURN (@Long)
END

这是我编写的一个T-SQL代码示例,用于计算CIDR地址的低位和高位IP范围。由于T-SQL缺乏位移操作符,所以代码比较混乱。

Declare @CidrIP varchar(50)
Set @CidrIP = '10.100.60.55/28'

Select dbo.[ConvertIPToLong](left(@CidrIP, patindex('%/%' , @CidrIP) - 1)) & (cast(4294967295 as bigint) ^ (Power(2, 32 - Cast(substring(@CidrIP, patindex('%/%' , @CidrIP) + 1, 2) as int)) - 1)) as LowRange,
       dbo.[ConvertIPToLong](left(@CidrIP, patindex('%/%' , @CidrIP) - 1)) & (cast(4294967295 as bigint) ^ (Power(2, 32 - Cast(substring(@CidrIP, patindex('%/%' , @CidrIP) + 1, 2) as int)) - 1)) + (Power(2, 32 - Cast(substring(@CidrIP, patindex('%/%' , @CidrIP) + 1, 2) as int)) - 1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接