在PHP中检测IPv6地址并将其正确存储在MySQL中.怎么样?

dik*_*era 4 php ipv6

我读了一些已经问过的问题,我发现这很有用,虽然我没有尝试过在PHP中使用IPv6地址

不过,说我在MySQL中有一个'禁令'表.我如何存储IPv6地址?该方法必须是通用的,即该字段必须能够包含ipv4或ipv6 addr.这也必须适用于我的users表中的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;
}
Run Code Online (Sandbox Code Playgroud)

Jak*_*ake 9

我正在搜索mysql中用于存储ipv6地址的最佳数据类型.我发现没有充分的理由使用VARCHAR(),只有很好的理由不要.

我使用BINARY(16),两个BIGINT UNSIGNED和DECIMAL数据类型进行了一些性能测试.

我创建了以下表格,填充了来自100个随机网络的2,000,000随机IP地址.

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
);
Run Code Online (Sandbox Code Playgroud)

然后我选择每个网络的所有IP地址并记录响应时间.twobigints表上的平均响应时间约为1秒,而二进制表上的平均响应时间约为百分之一秒.

这是查询.

注意:

X_ [HIGH/LOW]是X的最高/最低有效64位

当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
Run Code Online (Sandbox Code Playgroud)

平均响应时间:

平均响应时间

BINARY_InnoDB  0.0119529819489
BINARY_MyISAM  0.0139244818687
DECIMAL_InnoDB 0.017379629612
DECIMAL_MyISAM 0.0179929423332
BIGINT_InnoDB  0.782350552082
BIGINT_MyISAM  1.07809265852
Run Code Online (Sandbox Code Playgroud)