Как бы вы сравнили IP-адрес?

Для моего серверного приложения мне нужно проверить, находится ли ip-адрес в нашем черном списке.

Каков наиболее эффективный способ сравнения ip-адресов? Будет ли преобразование IP-адреса в целое и эффективное сравнение?

Ответ 1

Зависит от того, на каком языке вы работаете, но IP-адрес обычно сохраняется как 32-разрядное целое число без знака, по крайней мере на сетевом уровне, что делает сравнения довольно быстрыми. Даже если это не так, если вы не разрабатываете высокопроизводительное приложение для переключения пакетов, это вряд ли будет узким местом производительности. Избегайте преждевременной оптимизации - создайте свою программу для проверки и масштабируемости, и если у вас есть проблемы с производительностью, вы можете использовать профилировщик, чтобы узнать, где узкие места.

Изменить: чтобы уточнить, адреса IPv4 хранятся как 32-разрядные целые числа, а также сетевая маска (что не требуется для сопоставления IP-адресов). Если вы используете более новый и в настоящее время более редкий IPv6, тогда адреса будут иметь длину 128 бит.

Ответ 2

32-битные целые числа - это путь, пока вы не начнете работать с 128-битными адресами IPv6.

Ответ 3

Вы имеете в виду, если вы должны сравнить его как текстовую строку или преобразовать int в int и сравнить как int?

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

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

Очевидно, это должно вас заинтересовать только в том случае, если ваш черный список содержит десятки тысяч или миллионы записей. Если у него есть только 10-20 записей, предпочтительнее использовать линейный поиск, и действительно, более интересным вопросом является текстовое сравнение и сравнение с целым числом.

Ответ 4

static public bool IsEqual(string ToCompare,
                                      string CompareAgainst)
  {

     return IPAddressToLongBackwards(ToCompare)==IPAddressToLongBackwards(CompareAgainst);
  }

static private uint IPAddressToLongBackwards(string IPAddr)
  {
     System.Net.IPAddress oIP=System.Net.IPAddress.Parse(IPAddr);
     byte[] byteIP=oIP.GetAddressBytes();


     uint ip=(uint)byteIP[0]<<24;
     ip+=(uint)byteIP[1]<<16;
     ip+=(uint)byteIP[2]<<8;
     ip+=(uint)byteIP[3];

     return ip;
  }

Если я правильно вас понимаю, это код для сравнения двух IP-адресов, вам это нужно? вы можете далее делать такие вещи, как...

static public bool IsGreater(string ToCompare,
                               string CompareAgainst)
  {

     return IPAddressToLongBackwards(ToCompare)>
        IPAddressToLongBackwards(CompareAgainst);
  }

потому что вы получили адресные байты... Если вам нравится, тогда проголосуйте за меня, но, пожалуйста, не проголосуйте за меня.

Ответ 5

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

Ответ 6

Используйте такой инструмент, как PeerGuardian, который запрещает входящие соединения TCP/IP на уровне драйвера на IP-адреса в черном списке. Высокая безопасность, не требуется код (возможно: очень безопасный, потому что не требуется код).

Ответ 7

Я сделал это, и я его протестировал, использование unsigned int (32 бит) является самым быстрым - я предполагаю, что вы сравниваете это со строковым представлением.

Еще одна вещь, которая может вам помочь, - это создать таблицу, в прошлом у меня было 2 colums: LowIP и HighIP; таким образом, я смог черным списком всех диапазонов IP с 1 записью записи и по-прежнему получать хорошую производительность, проверяя IP в диапазоне.

Ответ 8

Я однажды унаследовал код, где кто-то думал, что сохранение IP-адресов как 4 int было действительно хорошим, за исключением того, что они потратили все свое время на преобразование в/из int.

Сохранение их в виде строк в базе данных было намного проще, и для этого требовался только один индекс. Вы будете удивлены, насколько хорошо сервер sql может индексировать строки, а не 4 столбца целых чисел. Но этот список IP не был для черного списка. База данных в оба конца довольно дорого.

Если база данных переполнена, сохраните их в словаре в памяти, но это просто предположение, поскольку мы не знаем, сколько вам нужно сравнивать. Поскольку большинство хэш-кодов являются 32-битными int, а адреса IPv4 - 32 бита, сам IP-адрес может быть хорошим хэш-кодом.

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

Если вы пытаетесь создать какое-то программное обеспечение внутри маршрутизатора, вам нужно будет ловить свою книгу данных и создать что-то вроде b-дерева.

Ответ 9

Radix или PATRICIA Trie являются оптимальной структурой для этого.

Проверьте источник C для потоков: http://www.splintered.net/sw/flow-tools/

Я работал над этим много лет назад.

Ответ 10

У вас есть проблема с эффективностью?

Если это так, то отправляйте код (или псевдокод), и мы можем выбрать его у трупы.

Если нет, я бы предложил попробовать что-то простое, например, сохранить записи в отсортированном списке и использовать существующую среду Sort() и Find().

Ответ 11

Целочисленные сравнения намного быстрее, чем сравнение строк.

Если вы сохраняете целые числа в отсортированном списке, вы можете найти их быстрее, чем в несортированном списке.

Ответ 12

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

но я бы точно знал обо всех решениях, если на этой операции будет иметь значение несколько миллисекунд (наносекунды!), -)