Обнаружение IPv6-адреса в PHP и его правильное хранение в MySQL. Как?

Я прочитал несколько из уже заданных вопросов, и я нашел, что это полезно, хотя я не пробовал его. Работа с адресами IPv6 в PHP

Тем не менее, скажем, у меня есть таблица «запретов» в MySQL. Как я могу хранить адрес IPv6? Метод должен быть универсальным, т. Е. Поле должно содержать либо ipv4, либо ipv6 addr. Это также должно применяться к моему полю ip_addr в моей таблице пользователей.

я бы обычно проверял, if(getip == $bans['ip']) { do something } Но моя функция getip для ipv4 afaik, и я задаюсь вопросом, будет ли это работать.

Функция, которую я использую,

 function getip() { if(isset($_SERVER['REMOTE_ADDR'])) { $ip = $_SERVER['REMOTE_ADDR']; } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { if(preg_match_all("#[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}#s", $_SERVER['HTTP_X_FORWARDED_FOR'], $addresses)) { foreach($addresses[0] as $key => $val) { if(!preg_match("#^(10|172\.16|192\.168)\.#", $val)) { $ip = $val; break; } } } } if(!isset($ip)) { if(isset($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } else { $ip = ''; } } $ip = preg_replace("#([^.0-9 ]*)#", "", $ip); return $ip; } 

Solutions Collecting From Web of "Обнаружение IPv6-адреса в PHP и его правильное хранение в MySQL. Как?"

Тем не менее, скажем, у меня есть таблица «запретов» в MySQL. Как я могу хранить адрес IPv6?

Вы можете сохранить его в простой колонке VARCHAR (40).
Учитывая пример IPv6 max составляет 40 байт:

 2001:0DB8:0000:0000:0000:0000:1428:57ab 

Эта coulmn будет также содержать IPv4

Я искал лучший тип данных в mysql для использования для хранения адреса ipv6 в последнее время. Я не нашел веских оснований для использования VARCHAR (), только для хороших причин НЕ .

Я провел некоторое тестирование производительности с помощью двух типов BINARY (16), двух BIGINT UNSIGNED и DECIMAL.

Я создал следующие таблицы, заполненные 2 000 000 случайных IP-адресов из 100 случайных сетей.

 CREATE TABLE ipv6_address_binary ( id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY, addr BINARY(16) NOT NULL UNIQUE ); CREATE TABLE ipv6_address_twobigints ( id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY, haddr BIGINT UNSIGNED NOT NULL, laddr BIGINT UNSIGNED NOT NULL, UNIQUE uidx (haddr, laddr) ); CREATE TABLE ipv6_address_decimal ( id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY, addr DECIMAL(39,0) NOT NULL UNIQUE ); 

Затем я выбираю все IP-адреса для каждой сети и записываю время ответа. Среднее время отклика в таблице twobigints составляет около 1 секунды, а на бинарной таблице – около одной сотой секунды.

Вот запросы.

Заметка:

X_ [HIGH / LOW] является самым / наименее значимым 64-битным элементом X

когда NETMASK_LOW равно 0, условие AND опущено, так как оно всегда возвращает true. не очень влияет на производительность.

 SELECT COUNT(*) FROM ipv6_address_twobigints WHERE haddr & NETMASK_HIGH = NETWORK_HIGH AND laddr & NETMASK_LOW = NETWORK_LOW SELECT COUNT(*) FROM ipv6_address_binary WHERE addr >= NETWORK AND addr <= BROADCAST SELECT COUNT(*) FROM ipv6_address_decimal WHERE addr >= NETWORK AND addr <= BROADCAST 

Среднее время ответа:

Среднее время ответа

 BINARY_InnoDB 0.0119529819489 BINARY_MyISAM 0.0139244818687 DECIMAL_InnoDB 0.017379629612 DECIMAL_MyISAM 0.0179929423332 BIGINT_InnoDB 0.782350552082 BIGINT_MyISAM 1.07809265852