2015-08-15 3 views
2

Мы используем базу данных GeoLite2, чтобы реализовать поиск IP ->. По соображениям производительности мы хотим импортировать CSV и преобразовать его в собственный формат.Преобразование записей CIDR в диапазон IP

CSV-представлена ​​следующим образом:

5.39.40.96/27,3017382,3017382,,0,0 
5.39.40.128/28,3017382,3017382,,0,0 
5.39.40.144/28,2635167,3017382,,0,0 
5.39.40.160/27,3017382,3017382,,0,0 
5.39.40.192/26,3017382,3017382,,0,0 
5.39.41.0/25,3017382,3017382,,0,0 
5.39.41.128/26,3017382,3017382,,0,0 
5.39.41.192/26,2635167,3017382,,0,0 
5.39.42.0/24,3017382,3017382,,0,0 
5.39.43.0/25,3017382,3017382,,0,0 

Таким образом, мы должны преобразовать CIDR нотации (пример: 5.39.40.96/27) в IP-адрес диапазона. (от IP - до IP)

Как это можно сделать на C#?

Примечание: Это не дубликат this question, так как я прошу о реализации C# и не Java.

ответ

6

Вот один из способов справиться с этим, без использования каких-либо функций библиотеки, чтобы дать понять, что происходит, и помочь, если кому-то понадобится реализовать его на других языках позже.

Код сначала преобразует CIDR в 32-разрядное число, затем создает маску для определения начального адреса, использует обратную сторону маски для определения конечного адреса и затем преобразует обратно в формат CIDR.

Обратите внимание, что обнаружение ошибок отсутствует, поэтому вход должен быть в формате a.b.c.d/m.

Преобразование IP-адреса - это просто конкатенация четырех октетов в форме большого конца (AABBCCDD) с использованием сдвигов бит.

Маска сообщает, сколько бит от самого значимого бита фиксировано, а 32 - это один диапазон IP, а 0 - весь диапазон IP. Таким образом, мы можем взять маску со всеми установленными битами и сдвинуть ее налево с 32-maskbits, чтобы определить фактическую маску.

Если мы установим maskbits бит в ноль, мы получим начало диапазона, поэтому мы и IP с масками. Если мы установим биты в единицу, мы получим конец диапазона, поэтому мы будем ИЛИ с отрицательными битами маски.

Печать IP-адреса в формате CIDR снова проста: просто разделите 32-битное значение на октеты и напишите их, разделенные точками.

using System; 

namespace CSTests 
{ 
    class Program 
    { 
     static string toip(uint ip) 
     { 
      return String.Format("{0}.{1}.{2}.{3}", ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 
     } 

     static void Main(string[] args) 
     { 
      string IP = "5.39.40.96/27"; 
      string[] parts = IP.Split('.', '/'); 

      uint ipnum = (Convert.ToUInt32(parts[0]) << 24) | 
       (Convert.ToUInt32(parts[1]) << 16) | 
       (Convert.ToUInt32(parts[2]) << 8) | 
       Convert.ToUInt32(parts[3]); 

      int maskbits = Convert.ToInt32(parts[4]); 
      uint mask = 0xffffffff; 
      mask <<= (32 - maskbits); 

      uint ipstart = ipnum & mask; 
      uint ipend = ipnum | (mask^0xffffffff); 

      Console.WriteLine(toip(ipstart) + " - " + toip(ipend)); 
     } 
    } 
} 

Выход:

5.39.40.96 - 5.39.40.127

+0

Вау, это действительно хороший ответ! Ваш код настолько короток и точнее. +1! – bytecode77

+1

Вместо '(mask^0xffffffff)' вы можете использовать '~ mask', чтобы сделать то же самое. –

0

Вот ваш ответ не является правильным Network ID должно быть: 5.39.40.64 и Broadcast ID shoudl быть: 5.39.40.95 и Используемый IP: 5.39.40.65 - 5.39.40.94

Я рассчитал также в Advance Subne t Калькулятор, вы можете увидеть результат на картинке enter image description here

Смежные вопросы