如何在 C# 中将 CIDR 转换为网络和 IP 地址范围?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1038002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to convert CIDR to network and IP address range in C#?
提问by Kurt
I have been looking around quite a bit to find some C# code to convert a network in CIDR notation (72.20.10.0/24) to an IP address range, without much luck. There are some threads about CIDR on stackoverlow, but none seems to have any C# code and cover exactly what I need. So I decided to cook it myself, and I did not want the code to rely on System.Net for any conversions in this version.
我一直在四处寻找一些 C# 代码来将 CIDR 表示法 (72.20.10.0/24) 中的网络转换为 IP 地址范围,但运气不佳。stackoverlow 上有一些关于 CIDR 的线程,但似乎没有任何线程包含任何 C# 代码并且完全涵盖了我需要的内容。所以我决定自己做饭,我不希望代码依赖 System.Net 在这个版本中进行任何转换。
Perhaps it may be of help to someone.
也许它可能对某人有所帮助。
References:
参考:
What's the best way to convert from network bitcount to netmask?
"Whatmask" C code from http://www.laffeycomputer.com/whatmask.html
来自http://www.laffeycomputer.com/whatmask.html 的“Whatmask”C 代码
Usage:
用法:
uint startIP, endIP;
Network2IpRange("72.20.10.0/24", out startIP, out endIP);
The code assumes 32 bits for everything.
该代码假定所有内容均为 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;
}
Feel free to submit your improvements.
请随时提交您的改进。
回答by nik
The steps would go like this for a network/maskBits
,
步骤将是这样的network/maskBits
,
You compute the mask
in one of these two ways,
你mask
用这两种方式之一计算,
mask = ~((1 << (32 - maskBits)) - 1) // or,
mask = ~(0xFFFFFFFF >> maskBits)
then the range is,
那么范围是,
StartIP = network
EndIP = network | ~mask
More precisely,
更确切地说,
StartIP = network & mask
EndIP = (network & mask) | ~mask
Where,
在哪里,
<<
is bitwise left shift (without rollover)&
is bitwise AND,|
is bitwise OR, and~
is bitwise INVERT.
<<
按位左移(无翻转)&
是按位与,|
是按位或,并且~
是按位 INVERT。
回答by nik
Here is how you do it for your example 72.20.10.0/24
,
这是你如何为你的例子做的72.20.10.0/24
,
Let Network
be 72.20.10.0
Mask
is ~((1 << (32-24)) - 1)
// orMask
is ~(0xFFFFFFFF >> 24)
让Network
是72.20.10.0
Mask
为~((1 << (32-24)) - 1)
//或者Mask
是~(0xFFFFFFFF >> 24)
- which is
0xFFFFFF00
- 这是
0xFFFFFF00
StartIPis -- (Network & Mask)
;
起始IP是-- (Network & Mask)
;
- which is
72.20.10.0 & 0xFFFFFF00
- 这是
72.20.10.0 & 0xFFFFFF00
EndIPis -- ((Network & Mask) | ~Mask)
;
EndIP是 -- ((Network & Mask) | ~Mask)
;
- which is
(72.20.10.0 & 0xFFFFFF00) | 0x000000FF
- 这是
(72.20.10.0 & 0xFFFFFF00) | 0x000000FF
This will be 72.20.10.0 -- 72.20.10.255
.
这将是72.20.10.0 -- 72.20.10.255
。
回答by nik
I recommend to use the C# IPNetwork class from Github.
我建议使用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);
It will ouput
它会输出
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
Have fun.
玩得开心。
回答by Bitmugger
Here's how to convert CIDR notation to a range in T-SQL, from my blog post:
以下是我的博客文章中将 CIDR 表示法转换为 T-SQL 范围的方法:
First pre-create this function in SQL Server (from http://www.stardeveloper.com).
首先在 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
This is a sample of T-SQL code I put together that will calculate the low and high IP ranges from a CIDR address. It's messy and I had to work around T-SQL's lack of bit shift operators.
这是我放在一起的 T-SQL 代码示例,它将根据 CIDR 地址计算低 IP 和高 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)