当给定IP地址和子网掩码时,如何计算IP范围?

45

当IP范围被写成aaa.bbb.ccc.ddd/netmask (CIDR表示法)时,我需要使用C#计算出此范围内第一个和最后一个包含的IP地址。

示例:

输入:192.168.0.1/25

结果:192.168.0.1 - 192.168.0.126


感谢Chris Weber提供CIDR笔记 :) - Anheledir
8个回答

65

我的好朋友Alessandro写了一篇关于C#中位运算符的好文章,你应该阅读它,这样你就会知道该怎么做。

很容易理解。如果将给定的IP地址转换为二进制,网络地址是其中所有主机位(子网掩码中的0)都为0的IP地址,而广播地址是其中所有主机位都为1的IP地址。

例如:

ip 192.168.33.72 mask 255.255.255.192

11111111.11111111.11111111.11000000 (subnet mask)
11000000.10101000.00100001.01001000 (ip address)

加粗的部分是主机位(其余是网络位)。如果将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

这是我读过的关于如何计算这些范围的最好解释。谢谢 :-) - Anheledir
你怎么知道是 /24、/25 还是 /26?这是什么意思? - Ken Le
好的,您在此发布的原则是手动计算的方式。第一个 IP 是 IP & 子网掩码 + 1,最后一个 IP 是 IP | ~子网掩码 - 1。 - rpbear

29

我会直接贴出代码:

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);

1
并非所有系统都是小端字节序。您应该测试 BitConverter.IsLittleEndian 来确定是否需要使用 Reverse() - JamieSee
3
我建议使用 mask = IPAddress.NetworkToHostOrder(mask)。 - sunside

8
取反掩码(与1异或),并与IP进行逻辑与运算。加上 1,这将成为起始范围。 将IP与掩码进行逻辑或运算。这将成为结束范围。

8
我从网络部署的职位中学到了这个快捷方式。它帮助了我很多,所以想和大家分享这个秘密。到目前为止,我在网上还没有找到一个比我知道的更容易的方法。
例如,一个网络 192.115.103.64 /27,它的范围是多少?
只需要记住子网掩码是0、128、192、224、240、248、252、254、255。
从/27我们知道 (11111111.11111111.11111111.11100000),从左边数起,它是最后一个八位数的第三个数字,等于 255.255.255.224 的子网掩码。(不要计算0,0是/24),因此是128、192、224等等。
这里涉及到数学:
使用子网掩码减去前一个列出的子网掩码,即224-192=32。
我们知道192.115.103.64是网络:64+32=96 (/27的下一个网络)。
这意味着我们有 .0 .32. 64. 96. 128. 160. 192. 224. (不能使用256,因为它是.255)
这是范围 64 -- 96。
网络是64。
第一个主机是65。(第一个网络+1)
最后一个主机是94。(广播 -1)
广播是95。(最后一个网络-1)

8
我建议使用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

玩得开心!


4

输入:192.168.0.1/25

掩码部分为:/25

要找到网络地址,请执行以下操作:

  • 将掩码从IP长度中减去(32-掩码)= 32-25 = 7,并从右侧取出这些位

  • 在给定的IP地址中,即:192.168.0.1,二进制表示为:11111111 11111111 00000000 00000001。现在,从右边取出7个'0',得到:1111111 11111111 00000000 00000000,转换成十进制为:192.168.0.0(这是网络地址)

要找到第一个有效/可用的IP地址,请将网络地址加上+1,即:192.168.0.1

要找到最后/广播地址,程序与查找网络地址相同,但是这里必须将(32-掩码)位从右边变为'1'

即:11111111 11111111 00000000 01111111,转换成十进制为:192.168.0.127

要找到最后一个有效/可用的IP地址,请从广播地址中减去1,即:192.168.0.126


2

2
你可能已经知道这一点,但如果想确认自己的理解是否正确,请访问http://www.subnet-calculator.com/ - 在那里你可以看到位数如何表示网络和主机部分的地址。

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