Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Optymalne wczytywanie i porównywanie adresów IP
Forum PHP.pl > Forum > PHP
WebCM
Istnieje bardzo długa lista 12635 zakazanych adresów IP w takiej postaci:

Kod
#komentarz
#inny komentarz
adres IP
adres IP
adres IP
...

Przy wczytywaniu trzeba pominąć komentarze, a następnie sprawdzić, czy adres IP użytkownika jest w bazie. Boty często atakują serwisy masowo, dlatego nie można zarżnąć serwera. Oto kilka sposobów:

1. Wczytać plik funkcją file() do tablicy, a następnie in_array()
2. Wczytać plik funkcją file_get_contents() jako ciąg znaków, a następnie strpos()
3. Zapisać plik jako tablicę PHP, a później include() i in_aray()
4. Wczytać plik do bazy danych, a potem sprawdzać prostym zapytaniem, czy IP jest w bazie
5. Inny sposób?

Zmierzyłem czas i pamięć sposobów 1,2,3,4 na PHP 5.3.1 pod kontrolą Windows XP. Wyniki:

1. Czas: 18.3 ms, pamięć: 1.35 MB, szczytowa: 1.86 MB
2. Czas: 2 ms, pamięć: 0.183 MB, szczytowa: 0.516 MB
3. Czas: 40 ms, pamięć: 1.316 MB, szczytowa: 3.078 MB
4. Czas: 0.7 ms, pamięć: 0.0012 MB, szczytowa: 0.341 MB, baza SQLite 3

Uwagi do poszczególnych sposobów:

1. Chociaż sposób zapewnia 100% skuteczność, jest wolny przy dużej liczbie linii
2. Działa szybko, ale może blokować adresy spoza listy, np. wzorzec 80.0.0.0 pasuje do 180.0.0.0
3. To mnie zaskoczyło, bo kod PHP z tablicą wczytuje się najdłużej i pożera pamięć!
4. Nie wiemy, ile pamięci używa baza. Odczyt z SQLite szybki, podobnie będzie w MySQL.

  1. //Metoda 1
  2. $lista = file('blacklist.txt');
  3. if(in_array($ip, $lista)) {}
  4.  
  5. //Metoda 2
  6. $lista = file_get_contents('blacklist.txt');
  7. if(strpos($lista,$ip)>0) {}
  8.  
  9. //Metoda 3
  10. require './blacklist.php';
  11. if(in_array($ip,$lista)) {}
  12.  
  13. //Metoda 4
  14. $q = $db->prepare('SELECT * FROM blacklist WHERE IP=?'); //IP typu INTEGER
  15. $q->execute(array(ip2long($ip)));
  16. $x = $q->fetchColumn();
  17.  
  18. //Metoda pomiarowa czasu
  19. $ip = 'dowolny IP (w moich testach był spoza czarnej listy)';
  20. $t = microtime(1);
  21. // .. w tym miejscu kod, który wczytuje listę i sprawdza IP ..
  22. $v = microtime(1);
  23. echo ($v-$t)*1000.0;
  24.  
  25. //Metoda pomiarowa pamięci
  26. $ip = 'tu adres IP';
  27. $m = xdebug_memory_usage();
  28. // .. w tym miejscu kod, który wczytuje listę i sprawdza IP ..
  29. $x = xdebug_memory_usage();
  30. var_dump(($x-$m)/1024/1024);
  31. var_dump((xdebug_peak_memory_usage())/1024/1024);
Fifi209
Zapisuj ip jako:
ip2long nie powinno być problemów przy porównaniu.

Baza z założonym indeksem będzie o wiele szybsza.
WebCM
Plik jest często aktualizowany, więc wygodniej będzie odczytywać go bezpośrednio tongue.gif

Tylko jak porównać IP jak najszybciej i bez dużego obciążenia serwera i bez konfliktu 8.8.8.8 z 88.8.8.8?

W ostateczności wykorzystam bazę danych, tylko trzeba będzie napisać mechanizm aktualizacji czarnej listy w CMS smile.gif

PS. Czarna lista jest w formacie .txt i pochodzi z systemu Sblam!
Fifi209
Cytat(WebCM @ 21.04.2012, 13:26:01 ) *
Plik jest często aktualizowany, więc wygodniej będzie odczytywać go bezpośrednio tongue.gif

To chyba właśnie wygodniej w bazie wink.gif

Cytat(WebCM @ 21.04.2012, 13:26:01 ) *
Tylko jak porównać IP jak najszybciej i bez dużego obciążenia serwera i bez konfliktu 8.8.8.8 z 88.8.8.8?

Przetestuj ip2long

Cytat(WebCM @ 21.04.2012, 13:26:01 ) *
W ostateczności wykorzystam bazę danych, tylko trzeba będzie napisać mechanizm aktualizacji czarnej listy w CMS smile.gif

Jeżeli czarna lista jest w bazie, wystarczy dodać triggera przy dodawaniu rekordu, aby dopisywał do innej tabeli albo od razu ładować do tabeli czarna lista
WebCM
Cytat(Fifi209)
Jeżeli czarna lista jest w bazie, wystarczy dodać triggera przy dodawaniu rekordu, aby dopisywał do innej tabeli albo od razu ładować do tabeli czarna lista

Czarna lista jest w pliku blacklist.txt.

W sposobie 2 problem blokowania adresów spoza listy można rozwiązać jak poniżej, o ile \n jest znakiem nowej linii:
  1. $ip = '\n8.8.8.8\n';
  2. $wynik = strpos($lista, $ip);

Chociaż baza jest najlepszym wyjściem i może zostanę przy tym.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.