给定 IP 地址和子网掩码,如何计算 CIDR?
Posted
技术标签:
【中文标题】给定 IP 地址和子网掩码,如何计算 CIDR?【英文标题】:Given an IP address and subnetmask, how do I calculate the CIDR? 【发布时间】:2011-01-31 06:22:33 【问题描述】:好吧,我似乎无法弄清楚:鉴于以下情况:
IP address = 192.168.1.0
Subnetmask = 255.255.255.240
使用 c#,我如何计算 CIDR 符号 192.168.1.0/28
?有没有简单的方法来实现这一目标?我错过了什么吗?
谢谢!
【问题讨论】:
【参考方案1】:256 - 240 = 16 = 2**4, 32 - 4 = 28
这不是一个真正的 C# 问题。
要从 IP 和掩码获取网络地址,您可以按字节将 and
应用于 IP 和掩码。您可以使用IPAddress.Parse()
和IPAddress.GetAddressBytes()
从字符串中获取字节。
【讨论】:
感谢您的信息。我知道我可以使用 IPAddress 类将字符串操作为 IP 地址和字节。我也了解子网/广播/cidr 计算等背后的逻辑......我只是无法将它放入一个简单的 c# 方法中,当我输入255.255.255.192
时,它给了我 26
我知道。那不是问题。没关系,我想通了。【参考方案2】:
我必须做同样的事情,没有新信息,但这个 sn-p 可能会为下一个在 C# 中寻找方法的人派上用场。 请注意,此方法仅计算连续 1 的数量,并留给您将其附加到 IP 的工作。
public class IPAddressHelper
public static UInt32 SubnetToCIDR(string subnetStr)
IPAddress subnetAddress = IPAddress.Parse(subnetStr);
byte[] ipParts = subnetAddress.GetAddressBytes();
UInt32 subnet = 16777216 * Convert.ToUInt32(ipParts[0]) + 65536 * Convert.ToUInt32(ipParts[1]) + 256 * Convert.ToUInt32(ipParts[2]) + Convert.ToUInt32(ipParts[3]);
UInt32 mask = 0x80000000;
UInt32 subnetConsecutiveOnes = 0;
for (int i = 0; i < 32; i++)
if (!(mask & subnet).Equals(mask)) break;
subnetConsecutiveOnes++;
mask = mask >> 1;
return subnetConsecutiveOnes;
【讨论】:
【参考方案3】:保持简单!
这仅适用于 IPv4,但由于 IPv6 仅支持像 /64
这样的 CIDR,因此在 fe80::1ff:fe23:4567:890a/64
中这样的计算是不必要的。
IPv4 网络掩码所需的一切:
int cidr = Convert.ToString(mask.Address, 2).Count( o => o == '1');
基于给定示例的解释:
IPAddress mask = new IPAddress(new byte[] 255, 255, 255, 240 );
// maskBinAsString = 11110000111101001111111111111111
string maskBinAsString = Convert.ToString(mask.Address, 2);
// cidr = 28
int cidr = Convert.ToString(mask.Address, 2).Count( o=> o == '1');
【讨论】:
IpAddress.Address 是过时的属性!【参考方案4】:我没有它作为 C# 代码,但这是 VB 中的答案。应该不难转换。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim someIP As Net.IPAddress = Net.IPAddress.Parse("192.168.1.10")
Dim someMASK As Net.IPAddress = Net.IPAddress.Parse("255.255.255.240")
Dim ipL As Long = IPtoLong(someIP)
Dim maskL As Long = IPtoLong(someMASK)
'Convert Mask to CIDR(1-30)
Dim oneBit As Long = &H80000000L
Dim CIDR As Integer = 0
For x As Integer = 31 To 0 Step -1
If (maskL And oneBit) = oneBit Then CIDR += 1 Else Exit For
oneBit = oneBit >> 1
Next
Dim answer As String = LongToIp(ipL And maskL) & " /" & CIDR.ToString
End Sub
Public Function IPtoLong(ByVal theIP As Net.IPAddress) As Long 'convert IP to number
Dim IPb() As Byte = theIP.GetAddressBytes 'get the octets
Dim addr As Long 'accumulator for address
For x As Integer = 0 To 3
addr = addr Or (CLng(IPb(x)) << (3 - x) * 8)
Next
Return addr
End Function
Public Function LongToIp(ByVal theIP As Long) As String 'convert number back to IP
Dim IPb(3) As Byte '4 octets
Dim addr As String = "" 'accumulator for address
Dim mask8 As Long = MaskFromCidr(8) 'create eight bit mask
For x = 0 To 3 'get the octets
IPb(x) = CByte((theIP And mask8) >> ((3 - x) * 8))
mask8 = mask8 >> 8
addr &= IPb(x).ToString & "." 'add current octet to string
Next
Return addr.TrimEnd("."c)
End Function
Private Function MaskFromCidr(ByVal CIDR As Integer) As Long
MaskFromCidr = CLng(2 ^ ((32 - CIDR)) - 1) Xor 4294967295L
End Function
【讨论】:
【参考方案5】:我的解决方案,先解析为IPAddress:
var Subnetmask = "255.255.255.240";
IPAddress ip = IPAddress.Parse(Subnetmask);
然后,检查掩码 ip 中设置位的计数:
var intAddress = (int)IPAddress.Address;
Console.WriteLine(NumberOfSetBits(intAddress)); //28
函数(来自https://***.com/a/12175897/1271037):
int NumberOfSetBits(int i)
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
【讨论】:
【参考方案6】:我知道这有点晚了,但我将上面的 dbasnett's answer VB.NET 代码转换为 C#(感谢 Telerik Code Converter)并将其放在 .NET Fiddle here 中并在下面包含我的转换:
public static void Main()
System.Net.IPAddress someIP = System.Net.IPAddress.Parse("192.168.1.23");
System.Net.IPAddress someMASK = System.Net.IPAddress.Parse("255.255.255.128");
long ipL = IPtoLong(someIP);
long maskL = IPtoLong(someMASK);
// Convert Mask to CIDR(1-30)
long oneBit = 0x80000000L;
int CIDR = 0;
for (int x = 31; x >= 0; x += -1)
if ((maskL & oneBit) == oneBit)
CIDR += 1;
else
break;
oneBit = oneBit >> 1;
string answer = LongToIp(ipL & maskL) + "/" + CIDR.ToString();
Console.Out.WriteLine("woah woah we woah " + answer);
public static long IPtoLong(System.Net.IPAddress theIP) // convert IP to number
byte[] IPb = theIP.GetAddressBytes(); // get the octets
long addr = 0; // accumulator for address
for (int x = 0; x <= 3; x++)
addr |= (System.Convert.ToInt64(IPb[x]) << (3 - x) * 8);
return addr;
public static string LongToIp(long theIP) // convert number back to IP
byte[] IPb = new byte[4]; // 4 octets
string addr = ""; // accumulator for address
long mask8 = MaskFromCidr(8); // create eight bit mask
for (var x = 0; x <= 3; x++) // get the octets
IPb[x] = System.Convert.ToByte((theIP & mask8) >> ((3 - x) * 8));
mask8 = mask8 >> 8;
addr += IPb[x].ToString() + "."; // add current octet to string
return addr.TrimEnd('.');
private static long MaskFromCidr(int CIDR)
return System.Convert.ToInt64(Math.Pow(2, ((32 - CIDR))) - 1) ^ 4294967295L;
【讨论】:
此解决方案不检查子网掩码的有效性。例如 255.255.255.253 将产生结果。一旦我们在子网掩码中找到零,我们需要检查所有剩余的位是否也是 0。【参考方案7】:见Get CIDR from netmask
用法:
var cidrnetmask = MaskToCIDR(IPAddress.Parse("255.0.0.0").GetAddressBytes());
这适用于 IPv4。为了支持 IPv6,可以扩大字节数,但希望没有人会尝试为 IPv6 使用旧式网络掩码 :o)
方法:
static int MaskToCIDR(byte[] bytes)
var b0 = bytes[0];
var b1 = bytes[1];
var b2 = bytes[2];
var b3 = bytes[3];
return
b3 != 0 ? (
(b3 & 0x01) != 0 ? 32 :
(b3 & 0x02) != 0 ? 31 :
(b3 & 0x04) != 0 ? 30 :
(b3 & 0x08) != 0 ? 29 :
(b3 & 0x10) != 0 ? 28 :
(b3 & 0x20) != 0 ? 27 :
(b3 & 0x40) != 0 ? 26 :
25 ) :
b2 != 0 ? (
(b2 & 0x01) != 0 ? 24 :
(b2 & 0x02) != 0 ? 23 :
(b2 & 0x04) != 0 ? 22 :
(b2 & 0x08) != 0 ? 21 :
(b2 & 0x10) != 0 ? 20 :
(b2 & 0x20) != 0 ? 19 :
(b2 & 0x40) != 0 ? 18 :
17 ) :
b1 != 0 ? (
(b1 & 0x01) != 0 ? 16 :
(b1 & 0x02) != 0 ? 15 :
(b1 & 0x04) != 0 ? 14 :
(b1 & 0x08) != 0 ? 13 :
(b1 & 0x10) != 0 ? 12 :
(b1 & 0x20) != 0 ? 11 :
(b1 & 0x40) != 0 ? 10 :
9 ) :
b0 != 0 ? (
(b0 & 0x01) != 0 ? 8 :
(b0 & 0x02) != 0 ? 7 :
(b0 & 0x04) != 0 ? 6 :
(b0 & 0x08) != 0 ? 5 :
(b0 & 0x10) != 0 ? 4 :
(b0 & 0x20) != 0 ? 3 :
(b0 & 0x40) != 0 ? 2 :
1 ) :
0;
【讨论】:
以上是关于给定 IP 地址和子网掩码,如何计算 CIDR?的主要内容,如果未能解决你的问题,请参考以下文章
写出专用IP地址的定义(采用两种方法表示,子网掩码的形式和CIDR前缀的形式)
计算机网络 王道考研2021 第四章:网络层 -- 子网划分与子网掩码无分类编址CIDR(构成超网)
IP地址NAT子网划分与子网掩码CIDR等网络层相关知识整理