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?

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top