【问题标题】:Storing and retrieving IPv4 and IPv6 addresses存储和检索 IPv4 和 IPv6 地址
【发布时间】:2016-09-18 03:05:11
【问题描述】:

关于在 PHP/MySQL 设置上存储 IPv4 和 IPv6 地址的最佳方式的 SO 上有一百万个问题,但答案要么已过时(仅限 IPv4),要么相互矛盾/不完整。

我创建这个问题是为了提供一个明确的答案,为您提供您需要知道的一切。

【问题讨论】:

    标签: php mysql ip-address ipv6 ipv4


    【解决方案1】:

    当您只需要担心 IPv4 时,您可以使用 PHP 的 ip2longlong2ip 快速轻松地将 IP 地址转换为整数。然而,如今,几乎每个人都应该期望在某个时候遇到一些 IPv6 地址,而且这种情况只会越来越多。

    一个常见且有效的解决方案是使用 PHPinet_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 地址的一种快速有效的方法。

    【讨论】:

    • MySQL 本身为 IPv4 提供等效函数 INET_ATON()INET_NTOA(),为 IPv4 和 IPv6 提供 since v5.6.3INET6_ATON()INET6_NTOA()
    • 不幸的是,您不仅需要担心 ip2long 和 long2ip;正如eggyal所说,也有mysql函数,但是后者(正确)是无符号的,而前者是有符号的,即不兼容。
    【解决方案2】:

    此时,如果您不构建应用程序以适应 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

    应该易于存储和搜索。

    我之前为此编写了一个帮助类,我刚刚将它推送到GithubPackagist,以防其他人发现它有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      • 2012-05-22
      • 2022-08-21
      • 1970-01-01
      • 2014-12-19
      • 1970-01-01
      相关资源
      最近更新 更多