我想存储IP地址以及用户注册,帖子,上传等。我以前的网站我总是使用ip2long/long2ip
并将其存储为UNSIGNED INT
,因为IPv4是我唯一的关心。所以我通过ip2long
运行IP地址,存储它,当我检索它时,使用long2ip
。但现在我想确保它更具未来性,并解决IPv4和IPv6问题。
到目前为止,我已经提出了一个处理IPv4和IPv6的功能:
function ipCheck()
{
// Get IP Address
if (!empty($_SERVER['HTTP_CLIENT_IP'])) // Shared client
{
$ipAddress = $_SERVER['HTTP_CLIENT_IP'];
}
else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) // Proxy address
{
$ipAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ipAddress = $_SERVER['REMOTE_ADDR']; // User viewing
}
// Over IP for testing
/*
IP Examples for testing
IPv4: 64.233.160.0
IPv6: 2607:f0d0:1002:51::4
IPv6: 2607:f0d0:1002:0051:0000:0000:0000:0004
*/
$ipAddress = '2607:f0d0:1002:0051:0000:0000:0000:0004'; // Comment out this line for actual IP
// Validate IP
if (filter_var($ipAddress, FILTER_VALIDATE_IP))
{
if (strpos($ipAddress, ':') !== false)
{
$ipType = 'IPv6';
$ipAddressDB = inet_pton($ipAddress);
}
else
{
$ipType = 'IPv4';
$ipAddressDB = ip2long($ipAddress);
}
}
else
{
$ipType = 'Invalid';
$ipAddressDB = $ipAddress;
}
// Display results
echo '<strong>IP Type: </strong>'.$ipType.'<br />',
'<strong>IP Address: </strong>'.$ipAddress.'<br />',
'<strong>DatabaseIP: </strong>'.$ipAddressDB;
}
ipCheck();
我个人没有IPv6地址,所以我为了测试目的而覆盖了$ipAddress
变量。
一切都适用于IPv4地址,但是当我使用$ipAddressDB
测试IP并且我真的不知道为什么时,IPv6地址的&(diamond-with-question-mark)(diamond-with-question-mark)Q
会返回值2607:f0d0:1002:0051:0000:0000:0000:0004
?我使用inet_pton
错了吗?我需要添加一些东西吗?是因为测试IPv6地址吗?
我假设一旦我开始工作,因为我们需要存储在2列中,我为数据库IP创建了2个变量,如果是IPv4,我将其分配给变量1并将变量2留空。然后,如果它是IPv6,我将它拆分,将前半部分放在变量1中,将第二部分放在变量2中。然后,当涉及插入/选择时,如果第二列为空,我们可以假设它是IPv4地址?
我甚至不能100%确定我正在尝试做的事实际上是否可行?如果没有,那么最好只是按原样获取IPv6地址(没有inet_pton
),然后就这样拆分它们吗?
答案 0 :(得分:1)
您正在以二进制形式查看地址。 “&安培;”是UTF-8 0x26,0xf0和0xd0无效UTF-8(显示为“ ”),“Q”是UTF-8 0x51,其他字节显示为空。在存储之前将字节串编码为十六进制(然后您可以完全相同地处理IPv4地址)。