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
。而且我们不需要使用 CONVERT
、HEX
/UNHEX
或 SUBSTR
。使用相同的表达式转换 IPv4 和 IPv6 地址:
INSERT ... ip_binary ... VALUES ( ... , INET6_ATON( :ip_string ) , ...
然后像这样将它们转换回字符串:
SELECT ... , INET6_NTOA( ip_binary ) AS ip_string , ...
CAST
、CONVERT
、SUBSTR
、HEX
/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
我使用如下命令将 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
。而且我们不需要使用 CONVERT
、HEX
/UNHEX
或 SUBSTR
。使用相同的表达式转换 IPv4 和 IPv6 地址:
INSERT ... ip_binary ... VALUES ( ... , INET6_ATON( :ip_string ) , ...
然后像这样将它们转换回字符串:
SELECT ... , INET6_NTOA( ip_binary ) AS ip_string , ...
CAST
、CONVERT
、SUBSTR
、HEX
/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