Como você compararia o endereço IP?
-
03-07-2019 - |
Pergunta
Para meu aplicativo de servidor, eu preciso verificar se um endereço IP está na nossa lista negra.
O que é a forma mais eficiente de comparar os endereços IP? Será que converter o endereço IP para inteiro e compará-los eficiente?
Solução
depende do que a linguagem que você está usando, mas um endereço IP é normalmente armazenado como bits 32 inteiro sem sinal, pelo menos na camada de rede, fazendo comparações bastante rápido. Mesmo se não é, a menos que você está projetando uma aplicação de comutação de pacotes de alto desempenho não é provável que seja um gargalo de desempenho. Evite otimização prematura -. Projetar seu programa para a capacidade de teste e escalabilidade e se você tiver problemas de desempenho, então você pode usar um profiler para ver quais são os gargalos
Editar: para esclarecer, os endereços IPv4 são armazenados como inteiros de 32 bits, além de uma máscara de rede (que não é necessário para comparações endereço IP). Se você estiver usando o mais recente e atualmente mais raro IPv6, os endereços serão 128 bits de comprimento.
Outras dicas
32-bit inteiros são o caminho a percorrer -. Até que você começar a lidar com endereços IPv6 de 128 bits
Você quer dizer se você deve comparar-lo como uma cadeia de texto ou int convertido para int e comparar como um int?
Isso não é normalmente o gargalo neste tipo de pesquisas. você pode apenas tentar implementar ambos os métodos e ver qual corre mais rápido.
O problema real com pesquisa de endereços IP é geralmente fazendo consultas eficientes, aproveitando-se do fato de que você está lidando com endereços IP e não apenas números aleatórios. para conseguir isso, você pode consultar LC trie e talvez este artigo
Obviamente, isso deve interessá-lo apenas se a sua lista negra detém dezenas de milhares ou milhões de entradas. Se ele tem apenas 10-20 entradas uma pesquisa linear deve ser preferido e de fato a questão mais interessante é a comparação textual vs comparação inteiro.
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;
}
Se eu entendi corretamente, este é o código para comparar dois endereços IP. Queres isto? Você pode ainda fazer tais coisas como:
static public bool IsGreater(string ToCompare,
string CompareAgainst)
{
return IPAddressToLongBackwards(ToCompare)>
IPAddressToLongBackwards(CompareAgainst);
}
porque você tem os bytes de endereço.
Sim eu descobri que para ser eficiente, será uma longa, porém, e é claro que você tem que IPs na lista negra de índice na forma inteiro.
Use uma ferramenta como o PeerGuardian que não permite conexões TCP / IP de entrada no nível do driver de IPs em uma lista negra. Altamente segura, sem código necessário (discutivelmente: altamente segura, , porque nenhum código necessário).
Eu fiz isso e eu testei, usando um int sem sinal (32 bits) é o mais rápido -. Estou assumindo que você está comparando esta com a representação de cadeia
Outra coisa que pode ajudá-lo é ao criar a tabela, no passado já tive 2 colums: LowIP e HighIP; dessa forma eu tenho sido capaz de faixas inteiras lista negra de IP de entrada com 1 registro e ainda obter um bom desempenho, marcando para o IP no intervalo.
eu código uma vez herdou onde alguém pensei que armazenar endereços IP como 4 int da era uma coisa muito boa, exceto que eles gastaram todo o seu tempo a conversão de / para int de.
Mantê-los como strings no banco de dados era muito mais fácil, e é necessário apenas um único índice. Você ficaria surpreso com o quão bem servidor sql cordas índice pode, em oposição a 4 colunas de números inteiros. Mas esta lista IP não era para lista negra. Um banco de dados de ida e volta é muito caro.
Se um banco de dados é um exagero, armazená-los em um dicionário na memória, mas isso é apenas uma suposição, uma vez que não tenho nenhuma idéia de quantos você precisa para comparar. Como a maioria dos hashcodes são 32-bit int de e endereços IPv4 são 32 bits, o endereço IP em si pode ser apenas um bom hashcode.
Mas, como outros apontam, a melhor opção poderia ser a de reduzir a carga sobre o servidor e comprar hardware especializado. Talvez você continuar recentemente na lista negra IP do na memória e, periodicamente, publicar novo de ao roteador.
Se você é o único a tentar fazer algum software dentro de um roteador, então você vai precisar para pescar para fora seus dados-estruturas reservar e criar algo como um b-tree.
O ou Radix PATRÍCIA Trie é a estrutura óptima para este.
Confira a fonte C para flow-tools: http://www.splintered.net/sw/flow-tools/
Eu trabalhei em isso há alguns anos.
Você tem um problema existente com eficiência?
Se sim, então por todos os meios postar o código (ou pseudo-código) e podemos escolher para o cadáver.
Se não, então gostaria de sugerir tentar algo simples como armazenar as entradas em uma lista ordenada e usando Sort()
existente do seu meio ambiente e Find()
.
comparações de inteiros são muito mais rápidos do que comparações de strings.
Se você armazenar os números inteiros em uma lista ordenada, você pode encontrá-los mais rapidamente do que em uma lista não ordenada.
Se você receber o endereço IP como uma string, comparando-a com uma corda pode ser mais eficiente do que convertendo-a representação inteira
mas eu tinha perfil ambas as soluções para ter certeza, se alguns milissegundos (nanossegundos!) Vão importa nessa operação; -)