简体   繁体   English

PHP的inet_pton()转换IPv4和IPv6

[英]PHP's inet_pton() to Convert both IPv4 and IPv6

When I use inet_pton() for FE80:0000:0000:0000:0202:B3FF:FE1E:8329 I get ) whatever that is. 当我将inet_pton()用于FE80:0000:0000:0000:0202:B3FF:FE1E:8329无论如何我都会得到 )

So then I added bin2hex() and get this fe800000000000000202b3fffe1e8329 better. 因此,我添加了bin2hex()并获得了更好的fe800000000000000202b3fffe1e8329

However, I was expecting a string of 16 not 32. 但是,我期望的是16而不是32的字符串。

And it gets even more inconsistent from there. 从那里变得更加不一致。

When converting 8.8.8.8 I get 08080808 string of 8. 转换8.8.8.8得到的是08080808字符串8。


Is there a way to achieve some consistency where everything is the same length or should I add this to the database as is? 有什么方法可以在所有长度都相同的情况下实现某种一致性,还是应该按原样将其添加到数据库中?

Am looking for an efficient/fast way to accomplish this that will result in a smaller string which would take less space on my database, without too many resources being wasted at it. 我正在寻找一种有效/快速的方法来完成此任务,以使它的字符串更小,占用的数据库空间更少,而不会浪费太多资源。

An IPv6 address is 128 bits long; IPv6地址的长度为128位; an IPv4 address is 32 bits long. IPv4地址的长度为32位。

This is no accident: one of the key motivations for creating IPv6 was that there are not enough possible 32-bit addresses for the needs of the modern internet. 这绝非偶然:创建IPv6的主要动机之一是没有足够的32位地址来满足现代Internet的需求。

) whatever that is. )无论是什么。

That is 128 bits, or 16 bytes, of binary data. 这是128位或16字节的二进制数据。 Attempting to view it as text won't give you anything very interesting, because not every combination of bits is a displayable character. 尝试以文本形式查看它不会给您带来任何有趣的效果,因为并非所有的位组合都是可显示的字符。

So then I added bin2hex() and get this fe800000000000000202b3fffe1e8329 所以我加了bin2hex()并得到了fe800000000000000202b3fffe1e8329

Converting the binary string to hexadecimal means representing each set of 4 bits as a character from the set 0123456789abcdef . 将二进制字符串转换为十六进制表示将4位的每个集合表示为0123456789abcdef一个字符。 The result is a string which is human readable, but 32 characters long (128 / 4 = 32). 结果是一个易于理解的字符串,但长度为32个字符(128/4 = 32)。

You might notice that the standard way of writing an IPv6 address is just this string with a : added every 4 characters for readability. 您可能会注意到,编写IPv6地址的标准方法就是添加一个字符串,每隔4个字符添加一个:以提高可读性。

When converting 8.8.8.8 I get 08080808 转换8.8.8.8时得到08080808

In binary, an IPv4 address would be 32 bits, or 4 bytes, long; 以二进制形式,IPv4地址的长度为32位或4个字节。 but again, those wouldn't all be printable characters. 但同样,这些字符也不都是可打印字符。 As hexadecimal, it is a string 8 characters long, because that is how many sets of 4 bits it contains (32 / 4 = 8). 作为十六进制,它是一个8个字符长的字符串,因为它包含多少组4位(32/4 = 8)。

Is there a way to achieve some consistency where everything is the same length 有没有办法在所有长度都相同的情况下实现某种一致性

The only way to make IPv4 addresses and IPv6 addresses the same length is to pad the IPv4 addresses with something on the left. 使IPv4地址和IPv6地址具有相同长度的唯一方法是在IPv4地址的左侧添加一些内容。 It's like saying "can I make John's name take up the same space as Samantha's". 这就像在说:“我能说出约翰的名字和萨曼莎的名字一样吗”。

Am looking for an efficient/fast way to accomplish this that will result in a smaller string which would take less space on my database 我正在寻找一种有效/快速的方法来完成此任务,从而使字符串更小,从而减少数据库占用的空间

The shortest universal representation is the binary one you got from inet_pton in the first place; 最短的通用表示形式是首先从inet_pton获得的二进制inet_pton just make sure to store it in a binary column in your database, not VarChar / Text /etc. 只要确保将其存储在数据库的二进制列中即可,而不是VarChar / Text / VarChar

Alternatively, the standard text format for IPv6 has a short-hand where one sequence of 0s in an address can be replaced by :: , so FE80:0000:0000:0000:0202:B3FF:FE1E:8329 can be abbreviated FE80::0202:B3FF:FE1E:8329 . 另外,IPv6的标准文本格式也有一个简写形式,其中地址中的一个0序列可以用::代替,因此FE80:0000:0000:0000:0202:B3FF:FE1E:8329可以缩写为FE80::0202:B3FF:FE1E:8329 I don't know of a PHP function for making such abbreviations, but it wouldn't be too hard to write one. 我不知道使用PHP这样的缩写,但是写一个并不难。

If you need it to be human-readable but short, you could play with other human-readable encodings of binary, like Base64 (which is natively supported by PHP ). 如果您需要它易于阅读但又简短,则可以使用其他人类可读的二进制编码,例如Base64( PHP本身支持 )。 A character in base64 represents 6 bits, but the string is conventionally padded to be a multiple of both 8 and 6 bits long, so an IPv6 address will take up 24 printable characters (128 bits + 16 bits padding / 6 = 24). base64中的一个字符代表6位,但是通常将字符串填充为8位和6位长的倍数,因此IPv6地址将占用24个可打印字符(128位+ 16位填充/ 6 = 24)。

Other rarer encodings are possible, such as " Base85 ", which use a wider range of characters to make the output shorter. 其他更罕见的编码也是可能的,例如“ Base85 ”,它使用更宽范围的字符来使输出更短。 However, they're all mathematically guaranteed to be longer than the binary representation, so you'll always need at least 16 bytes. 但是,从数学上讲,它们都比二进制表示法长,因此您始终至少需要16个字节。

In my opinion you should save them as they since these both are 2 different things. 我认为您应该保存它们,因为它们都是2种不同的东西。 Even if both are designed for the same purpose. 即使两者都是出于相同目的而设计的。

Still if you want to get these both along you would most Likely take these actions : * calculate the decimal value of the ipv6 since it's hexadecimal or the other way around. 尽管如此,如果您想同时实现这两种方法,则最有可能采取以下措施:*计算ipv6的十进制值,因为它是十六进制的或相反。 * ipv6 is 2^128 and ipv4 is 2^32. * ipv6为2 ^ 128,ipv4为2 ^ 32。 You need to calculate the differences to have the same base on both sides. 您需要计算差异以使双方的底数相同。 This could be accomplished with placeholders (zeros at the start as example) until you have the same Potency *You now could save them as even strings in the databases. 可以使用占位符(例如,开头为零)来完成此操作,直到您具有相同的效价为止*您现在可以将它们另存为数据库中的字符串。

I sadly can't give examples since I'm on my mobile phone. 不幸的是,由于我正在使用手机,因此我无法给出示例。 But I think it should be clear. 但是我认为应该清楚。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM