Как вычислить диапазон IP, когда задан IP-адрес и сетевая маска?

когда IP-диапазон записывается как aaa.ГЭБ.КТС.ddd / netmask (обозначение CIDR) мне нужно вычислить первый и последний включенный ip-адрес в этом диапазоне с C#.

пример:

вход: 192.168.0.1/25

результат: 192.168.0.1-192.168.0.126

8 ответов


мой хороший друг Алессандро есть хороший пост что касается битовых операторов в C#, вы должны прочитать об этом, чтобы знать, что делать.

это довольно легко. Если вы разбиваете IP, данный вам двоичный, сетевой адрес-это ip-адрес, где все биты хоста (0 в маске подсети) равны 0,а последний адрес, широковещательный адрес, где все биты хоста равны 1.

для пример:

ip 192.168.33.72 mask 255.255.255.192

11111111.11111111.11111111.11000000 (subnet mask)
11000000.10101000.00100001.01001000 (ip address)

жирным частей является хозяином бит (остальные биты сети). Если вы включите все биты хоста в 0 на IP, вы получите первый возможный 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);

Я узнал этот ярлык, работая в позиции сетевого развертывания. Это так помогло мне, что я решил поделиться этим секретом со всеми. До сих пор я не смог найти более простой способ онлайн, о котором я знаю.

например, сеть 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 1111111111.11111111.111111.11111111110 / 31

255.255.255.252 1111111111.11111111.11111111.1111111100 / 30

255.255.255.248 1111111111.11111111.11111111.1111111000 / 29

11111111.11111111.11111111.11110000 255.255.255.240 /28

11111111.11111111.11111111.11100000 255.255.255.224 /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..и т. д.

здесь, где математика входит в:

используйте маску подсети-маску подсети предыдущей указанной маски подсети в этом дело 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)


инвертировать маску (XOR с единицами), и это с IP. Добавить 1. Это будет стартовый диапазон. Или IP с маской. Это будет конечный диапазон.


Я бы рекомендовал использовать библиотеку 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

удачи !


Я знаю, что это более старый вопрос, но я нашел эту отличную библиотеку на nuget, которая, кажется, делает для меня трюк:

http://nuget.org/packages/TakeIo.NetworkAddress/


вы, возможно, уже знаете это, но чтобы проверить, что вы получаете этот материал правильно, посмотрите на http://www.subnet-calculator.com/ - Вы можете увидеть там, как биты представляют сетевые и хост-части адреса.


вход: 192.168.0.1/25

маска Эта часть: /25

чтобы найти сетевой адрес, выполните следующие действия:

  • вычесть маску из длины ip (32-mask) = 32 - 25 = 7 и взять эти биты справа

  • в данном ip-адресе Т. е.: 192.168.0.1 в двоичной: 11111111 11111111 00000000 00000001 Теперь, взяв 7 бит справа '0' 1111111 11111111 00000000 00000000 Который в decimal: 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