存储和检索 IPv4 和 IPv6 地址
Storing and retrieving IPv4 and IPv6 addresses
关于在 PHP/MySQL 设置上存储 IPv4 和 IPv6 地址的最佳方式,SO 上有一百万个问题,但答案要么已过时(仅 IPv4),要么是 contradictory/incomplete.
我提出这个问题是为了给您一个明确的答案,为您提供您需要知道的一切。
当您只需要担心 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 地址的快速有效方法。
在这个时间点,如果您不构建您的应用程序以适应 IPv6,那么您就是在伤害自己,并且随着时间的推移,这将变得更加真实。出于这个原因,我已经开始以 IPv6 格式存储 所有 IP 地址,并对 IPv4 地址使用 6to4 表示法。
6to4 的 TL;DR 是:
The first 16 bits of the prefix are always 2002:, the next 32 bits are the IPv4 address, and the last 16 bits of the prefix are [not important for this purpose]
假设您的 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
应该易于存储和搜索。
我之前为此编写了一个帮助程序 class,我只是将它推到 Github and Packagist 以防其他人发现它有用。
关于在 PHP/MySQL 设置上存储 IPv4 和 IPv6 地址的最佳方式,SO 上有一百万个问题,但答案要么已过时(仅 IPv4),要么是 contradictory/incomplete.
我提出这个问题是为了给您一个明确的答案,为您提供您需要知道的一切。
当您只需要担心 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 地址的快速有效方法。
在这个时间点,如果您不构建您的应用程序以适应 IPv6,那么您就是在伤害自己,并且随着时间的推移,这将变得更加真实。出于这个原因,我已经开始以 IPv6 格式存储 所有 IP 地址,并对 IPv4 地址使用 6to4 表示法。
6to4 的 TL;DR 是:
The first 16 bits of the prefix are always 2002:, the next 32 bits are the IPv4 address, and the last 16 bits of the prefix are [not important for this purpose]
假设您的 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
应该易于存储和搜索。
我之前为此编写了一个帮助程序 class,我只是将它推到 Github and Packagist 以防其他人发现它有用。