当 IP 范围写为 aaa.bbb.ccc.ddd/netmask(CIDR 表示法)时,我需要使用 C# 计算此范围内包含的第一个和最后一个 IP 地址。
例子:
输入: 192.168.0.1/25
结果: 192.168.0.1 - 192.168.0.126
我的好朋友Alessandro有一篇关于 C# 中的位运算符的好文章,您应该阅读它,以便您知道该怎么做。
这很容易。如果你把给你的IP分解成二进制,网络地址就是所有主机位(子网掩码中的0)都是0的IP地址,最后一个地址,广播地址,是所有主机的地址位为 1。
例如:
ip 192.168.33.72 mask 255.255.255.192
11111111.11111111.11111111.11000000 (subnet mask)
11000000.10101000.00100001.01001000 (ip address)
粗体部分是 HOST 位(其余是网络位)。如果您将 IP 上的所有主机位都设置为 0,您将获得第一个可能的 IP:
11000000.10101000.00100001.01000000 (192.168.33.64)
如果您将所有主机位都设置为 1,那么您将获得最后一个可能的 IP(也就是广播地址):
11000000.10101000.00100001.01111111 (192.168.33.127)
所以对于我的例子:
the network is "192.168.33.64/26":
Network address: 192.168.33.64
First usable: 192.168.33.65 (you can use the network address, but generally this is considered bad practice)
Last useable: 192.168.33.126
Broadcast address: 192.168.33.127
我将发布代码:
IPAddress ip = new IPAddress(new byte[] { 192, 168, 0, 1 });
int bits = 25;
uint mask = ~(uint.MaxValue >> bits);
// Convert the IP address to bytes.
byte[] ipBytes = ip.GetAddressBytes();
// BitConverter gives bytes in opposite order to GetAddressBytes().
byte[] maskBytes = BitConverter.GetBytes(mask).Reverse().ToArray();
byte[] startIPBytes = new byte[ipBytes.Length];
byte[] endIPBytes = new byte[ipBytes.Length];
// Calculate the bytes of the start and end IP addresses.
for (int i = 0; i < ipBytes.Length; i++)
{
startIPBytes[i] = (byte)(ipBytes[i] & maskBytes[i]);
endIPBytes[i] = (byte)(ipBytes[i] | ~maskBytes[i]);
}
// Convert the bytes to IP addresses.
IPAddress startIP = new IPAddress(startIPBytes);
IPAddress endIP = new IPAddress(endIPBytes);
反转掩码(与一个异或),并将其与 IP。加 1。这将是起始范围。或带掩码的 IP。这将是结束范围。
我在网络部署位置工作时学到了这个捷径。它对我帮助很大,我想我会与大家分享这个秘密。到目前为止,我还没有找到我所知道的更简单的在线方法。
例如一个网络 192.115.103.64 /27,范围是多少?
只要记住子网掩码是 0, 128, 192, 224, 240, 248, 252, 254, 255
255.255.255.255 11111111.11111111.11111111.11111111 /32
255.255.255.254 11111111.11111111.11111111.11111110 /31
255.255.255.252 11111111.11111111.11111111.11111100 /30
255.255.255.248 11111111.11111111.11111111.11111000 /29
255.255.255.240 11111111.11111111.11111111.11110000 /28
255.255.255.224 11111111.11111111.11111111.11100000 /27
255.255.255.192 11111111.11111111.11111111.11000000 /26
255.255.255.128 11111111.11111111.11111111.10000000 /25
255.255.255.0 11111111.11111111.11111111.00000000 /24
从 /27 我们知道 (11111111.11111111.11111111.11100000)。从左数到最后一个八位字节的第三个数字,等于 255.255.255.224 子网掩码。(不要算 0,0 是 /24)所以 128、192、224..etc
这里的数学进来:
使用子网掩码 - 在这种情况下,之前列出的子网掩码的子网掩码 224-192=32
我们知道 192.115.103.64 是网络:64 + 32 = 96(/27 的下一个网络)
这意味着我们有 .0 .32。64. 96. 128. 160. 192. 224. (不能使用 256,因为它是 0.255)
这是范围 64 - 96。
网络是64。
第一个主机是65。(第一个网络+1)
最后主持人是94。(广播-1)
广播是95。(最后一个网络-1)
我建议使用 IPNetwork 库https://github.com/lduchosal/ipnetwork。从版本 2 开始,它也支持 IPv4 和 IPv6。
IPv4
IPNetwork ipnetwork = IPNetwork.Parse("192.168.0.1/25");
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.128
Broadcast : 192.168.0.127
FirstUsable : 192.168.0.1
LastUsable : 192.168.0.126
Usable : 126
Cidr : 25
玩得开心 !
输入:192.168.0.1/25
面具是这部分:/25
要查找网络地址,请执行以下操作:
从 ip 长度 (32 - mask) = 32 - 25 = 7 中减去掩码,然后从右边取出这些位
在给定的 ip 地址192.168.0.1
中,即:二进制是:
11111111 11111111 00000000 00000001
现在,从右边的 '0' 中取 7 位
1111111 11111111 00000000 00000000
,十进制是:(
192.168.0.0
这是网络地址)
要找到第一个有效/可用的 IP 地址,请将 +1 添加到网络地址,即:192.168.0.1
查找最后/广播地址的过程与查找网络地址的过程相同,但在这里您必须将(32-mask)位从右到“1”
即:11111111 11111111 00000000 01111111
十进制是192.168.0.127
要找到最后一个有效/可用的 IP 地址,请从广播地址中减去 1,即:192.168.0.126
我知道这是一个较老的问题,但我在 nuget 上发现了这个漂亮的库,它似乎对我有用:
您可能已经知道这一点,但要检查您是否正确了解这些内容,请查看http://www.subnet-calculator.com/ - 您可以在那里看到这些位如何表示地址的网络和主机部分.