IP地址二进制到人类可读

时间:2018-04-08 19:19:51

标签: mysql binary ipv6 ipv4

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

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

我的专栏是:

varbinary(16)

我已经尝试使用mysql函数INET6_NTOA将其转换回IPv4格式,但没有任何运气。

我需要的IP是:

66.249.64.90

DB值为:

42f9405a000000000000000000000000

INET6_NTOA给了我:

42f9:405a::

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

这是我的全部问题:

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

以及回复:

phpmyadmin output

感谢。

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

1 个答案:

答案 0 :(得分:2)

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

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

我认为这个问题可以追溯到问题的第一行SQL,即BINARY(16)。这将返回16个字节的固定长度。从为IPv4地址返回的四个字节开始,然后在右边用零填充,最长为16个字节。

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

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

如果我们更正stats表的内容,将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包含字符串表示,我们可以重新转换为二进制表示。

 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