【发布时间】:2016-09-18 03:05:11
【问题描述】:
关于在 PHP/MySQL 设置上存储 IPv4 和 IPv6 地址的最佳方式的 SO 上有一百万个问题,但答案要么已过时(仅限 IPv4),要么相互矛盾/不完整。
我创建这个问题是为了提供一个明确的答案,为您提供您需要知道的一切。
【问题讨论】:
标签: php mysql ip-address ipv6 ipv4
关于在 PHP/MySQL 设置上存储 IPv4 和 IPv6 地址的最佳方式的 SO 上有一百万个问题,但答案要么已过时(仅限 IPv4),要么相互矛盾/不完整。
我创建这个问题是为了提供一个明确的答案,为您提供您需要知道的一切。
【问题讨论】:
标签: php mysql ip-address ipv6 ipv4
当您只需要担心 IPv4 时,您可以使用 PHP 的 ip2long 和 long2ip 快速轻松地将 IP 地址转换为整数。然而,如今,几乎每个人都应该期望在某个时候遇到一些 IPv6 地址,而且这种情况只会越来越多。
一个常见且有效的解决方案是使用 PHP 的 inet_pton function(同时处理 IPv4 和 v6),然后将结果存储在数据库中的 VARBINARY(16) 列中.
假设我们有一个 IPv6 地址,例如:FE80:0000:0000:0000:0202:B3FF:FE1E:8329
当使用inet_pton 转换并存储在VARBINARY(16) 列中时,它看起来像这样:
0xfe800000000000000202b3fffe1e8329
然后您可以从数据库中检索它并使用inet_ntop 显示它。
例如:
echo inet_ntop($ipAddressFromDB);
这是在 MySQL 数据库中存储 IP 地址的一种快速有效的方法。
【讨论】:
INET_ATON() 和 INET_NTOA(),为 IPv4 和 IPv6 提供 since v5.6.3、INET6_ATON() 和 INET6_NTOA()。
此时,如果您不构建应用程序以适应 IPv6,那么您就是在损害自己的利益,而且随着时间的推移,这种情况会变得更加真实。出于这个原因,我开始以 IPv6 格式存储 所有 IP 地址,并对 IPv4 地址使用6to4 表示法。
6to4 的 TL;DR 是:
前缀的前 16 位始终是 2002:,接下来的 32 位是 IPv4 地址,前缀的后 16 位[对此不重要]
假设您的 IP 地址是 222.173.190.239,我们通过以下方式将其转换为 6to4 表示法:
sprintf('2002:%s::', implode(':', str_split(str_pad(dechex(ip2long($addr)), 8, '0', STR_PAD_LEFT), 2)));
变成:2002:de:ad:be:ef::
您将其转换为二进制形式进行存储:inet_pton('2002:de:ad:be:ef::');
给出 16 字节二进制文件:0x200200de00ad00be00ef000000000000
应该易于存储和搜索。
【讨论】: