PHP的inet_pton()转换IPv4和IPv6

时间:2018-09-24 17:04:10

标签: php

当我将inet_pton()用于FE80:0000:0000:0000:0202:B3FF:FE1E:8329时,无论如何我都会得到������)

因此,我添加了bin2hex(),并使它fe800000000000000202b3fffe1e8329更好。

但是,我期望的是16而不是32的字符串。

从那里变得更加不一致。

转换8.8.8.8时得到的08080808字符串为8。


在所有长度都相同的情况下,是否可以实现某种一致性?还是应该将其原样添加到数据库中?

我正在寻找一种高效/快速的方法来实现这一点,从而产生一个较小的字符串,该字符串将占用我的数据库更少的空间,而不会浪费太多的资源。

2 个答案:

答案 0 :(得分:6)

IPv6地址的长度为128位; IPv4地址的长度为32位。

这绝非偶然:创建IPv6的主要动机之一是没有足够的32位地址来满足现代Internet的需求。

  

������)无关。

即128位或16字节的二进制数据。尝试将其视为文本不会给您带来任何有趣的效果,因为并非每个位组合都是可显示的字符。

  

所以我添加了bin2hex()并得到了fe800000000000000202b3fffe1e8329

将二进制字符串转换为十六进制意味着将每个4位集合表示为一组0123456789abcdef中的一个字符。结果是一个易于理解的字符串,但长度为32个字符(128/4 = 32)。

您可能会注意到,写入IPv6地址的标准方法就是将此字符串加上一个:,该字符串每隔4个字符添加一次,以提高可读性。

  

转换8.8.8.8时得到08080808

以二进制形式,IPv4地址的长度为32位或4个字节;但同样,这些字符也不都是可打印字符。作为十六进制,它是一个8个字符长的字符串,因为它包含多少组4位(32/4 = 8)。

  

有没有办法在所有长度都相同的情况下实现某种一致性

使IPv4地址和IPv6地址具有相同长度的唯一方法是在IPv4地址的左侧添加一些内容。这就像在说:“我能说出约翰的名字和萨曼莎的名字一样吗?”

  

我正在寻找一种高效/快速的方法来实现这一点,从而产生一个较小的字符串,这将占用我的数据库更少的空间

最短的通用表示形式是首先从inet_pton获得的二进制表示形式;只需确保将其存储在数据库的二进制列中即可,而不要存储在VarChar / Text / etc中。

或者,IPv6的标准文本格式有一个简写形式,其中地址中的一个0序列可以用::代替,因此FE80:0000:0000:0000:0202:B3FF:FE1E:8329可以缩写为FE80::0202:B3FF:FE1E:8329。我不知道使用PHP这样的缩写,但是写一个并不难。

如果您需要它易于阅读但又简短,则可以使用其他人类可读的二进制编码,例如Base64(即natively supported by PHP)。 base64中的一个字符代表6位,但是通常将字符串填充为8位和6位长的倍数,因此IPv6地址将占用24个可打印字符(128位+ 16位填充/ 6 = 24)。

其他更罕见的编码也是可能的,例如“ Base85”,它使用更大范围的字符来使输出更短。但是,从数学上讲,它们全部都比二进制表示法长,因此您始终至少需要16个字节。

答案 1 :(得分:0)

我认为您应该保存它们,因为它们都是2种不同的东西。即使两者都是出于相同目的而设计。

如果您想同时实现这两个目标,则最有可能采取以下行动: *计算ipv6的十进制值,因为它是十六进制或相反。 * ipv6为2 ^ 128,ipv4为2 ^ 32。您需要计算差异以使双方的底数相同。可以使用占位符(例如,开头为零)来完成此操作,直到您拥有相同的效价为止 *您现在可以将它们另存为数据库中的字符串。

可悲的是,由于我正在使用手机,因此我无法提供示例。但是我认为应该清楚。