IP 地址二进制到人类可读

IP Address Binary to Human Readable

我使用如下命令将 IP 地址存储在数据库中:

cast(INET6_ATON(trim(:ipbinary)) as binary(16)))

我的专栏是:

varbinary(16)

我试过使用 mysql 函数 INET6_NTOA 将其转换回 IPv4 格式,但没有成功。

我需要的IP是:

66.249.64.90

数据库值为:

42f9405a000000000000000000000000

INET6_NTOA 给我:

42f9:405a::

INET6_NTOA(UNHEX( 给了我 NULL 回复。我使用 PHP 作为我的脚本语言,所以如果那里也有一个函数,我也可以使用它。

这是我的完整查询:

SELECT delete_ip, INET6_NTOA(ip_binary), ip_binary FROM `stats`

这是回复:

谢谢。

(我不能只使用 delete_ip,因为顾名思义,该列将被删除。)

它没有转换回 IPv4 人类可读格式,它正在转换为 IPv6,因为 INET6_NTOA(二进制值)的参数是 16 个字节。

该函数将其视为 IPv6 地址的表示,而不是 IPv4 地址,后者只有四个字节。


我想这个问题可以追溯到问题中SQL的第一行,转换为BINARY(16)。它返回一个 固定长度 的 16 字节。从为 IPv4 地址返回的四个字节开始,然后在右侧用零填充,直到 16 个字节的长度。


如果我们移除固定长度的转换,并允许 INET6_ATON 函数的结果只有四个字节,会发生什么情况?

当存储在数据库中的值只有四个字节时会发生什么?

如果我们更正 stats table 的内容,将 16 字节的二进制值(IPv6 地址的表示形式)更改为 IPv4 地址的四字节二进制表示形式会怎样

UPDATE `stats` 
   SET ip_binary = INET6_ATON('66.249.64.90')
 WHERE ip_binary = CAST(INET6_ATON('66.249.64.90') AS BINARY(16))

--或者--

UPDATE `stats` 
   SET ip_binary = X'42f9405a' + 0 
 WHERE ip_binary = X'42f9405a000000000000000000000000' + 0

跟进

问题说...“使用 [表达式] 在数据库 [列] 中存储 IP 地址,如下所示:

 cast(INET6_ATON(trim(:ipbinary)) as binary(16)))

我们不需要使用 CAST。而且我们不需要使用 CONVERTHEX/UNHEXSUBSTR。使用相同的表达式转换 IPv4 和 IPv6 地址:

  INSERT ... ip_binary ... VALUES ( ... , INET6_ATON( :ip_string ) , ...

然后像这样将它们转换回字符串:

 SELECT ... , INET6_NTOA( ip_binary ) AS ip_string , ... 

CASTCONVERTSUBSTRHEX/UNHEX 的冗长代码令人困惑,导致无法正常工作。


要更正已存储在数据库中的值,我们需要一种方法来区分 16 字节二进制表示中哪些实际上是 IPv4 地址,哪些应该存储为 4 字节。

如果ip_delete包含字符串表示,我们可以re-convert到二进制表示。

 UPDATE `stats`
    SET ip_binary = INET6_ATON( ip_delete ) 

演示

CREATE TABLE `addr` (ip_string VARCHAR(45), ip_binary VARBINARY(16)) ;

INSERT INTO `addr` VALUES ( '66.249.64.90'         , INET6_ATON( '66.249.64.90'         ));
INSERT INTO `addr` VALUES ( '127.0.0.1'            , INET6_ATON( '127.0.0.1'            ));
INSERT INTO `addr` VALUES ( '192.168.1.1'          , INET6_ATON( '192.168.0.1'          ));
INSERT INTO `addr` VALUES ( '2001:4860:4860::8888' , INET6_ATON( '2001:4860:4860::8888' ));

SELECT ip_string, HEX(ip_binary), INET6_NTOA(ip_binary) FROM `addr` ;

ip_string             HEX(ip_binary)                    INET6_NTOA(ip_binary)
--------------------  --------------------------------  -----------------------
66.249.64.90          42F9405A                          66.249.64.90
127.0.0.1             7F000001                          127.0.0.1
192.168.1.1           C0A80001                          192.168.0.1
2001:4860:4860::8888  20014860486000000000000000008888  2001:4860:4860::8888