将 IPv4、IPv6 地址存储为字符串的大小

Posted

技术标签:

【中文标题】将 IPv4、IPv6 地址存储为字符串的大小【英文标题】:Size for storing IPv4, IPv6 addresses as a string 【发布时间】:2011-03-28 04:29:00 【问题描述】:

mysql 数据库中以字符串形式存储 IPv4、IPv6 地址的理想大小应该是多少。 varchar(32) 是否足够?

【问题讨论】:

@Col:在当前任何稳定的 MySQL 版本中都没有好的选择。 至少 2 个 bigint 可以替代 ipv6。并即时从字符串 ipv4 转换为字符串 ipv6,正如问题和答案所假设的那样 @Col:这样更好吗?您仍然需要在应用程序代码中进行转换,而且任何不得不深入数据库本身的人都无法真正读取该死的地址,因为 IPv6 没有内置的 INET_NTOA 实现。 @Nicholas 你仍然可以在地址上使用二进制数学。或者只是在 BETWEEN 之间找到一个范围。用字符串地址试试吧。 @Col:使用正确规范化的字符串地址做任何你想做的事情都非常容易。你所失去的只是性能,而且 OP 不太可能会做足够多的此类查询来影响那么大。 【参考方案1】:

假设字符串中的文本表示:

15 个字符用于 IPv4(xxx.xxx.xxx.xxx 格式,12+3 分隔符) 45 characters 用于 IPv6

这些是字符串的最大长度。

存储为字符串的替代方案:

IPv4 是 32 位的,所以可以保存 4 个字节的 MySQL 数据类型就可以了,使用INT UNSIGNED 以及INET_ATONINET_NTOA 来处理从地址到数字的转换,以及从数字到数字的转换。地址
SELECT INET_ATON('209.207.224.40');
        -> 3520061480

SELECT INET_NTOA(3520061480);
        -> '209.207.224.40'
对于 IPv6,不幸的是 MySQL 没有 16 字节的数据类型,但是可以将 IPv6 转换为规范形式,然后将它们分成 2 个BIGINT(8 个字节),但这将使用两个字段。

【讨论】:

这是不正确的。您可以以 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:AAA.BBB.CCC.DDD 的形式编写 IPv6 地址,其中最后一部分是嵌入的 ipv4 样式地址。我认为长度是 45? @John:嗯,不,不要存储所有的零。 IPV4 映射地址应规范化为::ffff:aaa.bbb.ccc.ddd。 (IPv4 映射地址是唯一应该以这种形式出现的地址,IPv4 映射地址的前 80 位始终为零。) @John,我只能用二进制写入它,它会占用更多空间,但就像你的 IPv4 位一样,它可以计算来自 128 位地址,因此没有必要,尤其是在 DB 中。 是的,当然,如果您明智的话,您只会以这种方式使用它。但我不认为将其用于随机 ipv6 地址实际上是非法的,因此您希望能够将其存储在您的数据库中。您当然可以将地址标准化为所有十六进制。但是我还是觉得有必要指出,合法地表示为字符串的ipv6地址可以是45个字符, @John,我认为嵌入 IPv6 时仍然是 128 位,最后 32 位 (96-128) 代表嵌入的 IPv4。【参考方案2】:

除了已经说过的,还有 Link-Local IPv6 地址。如果您想保留地址以便可以使用字符串创建连接,您还需要保留范围 ID。 在 Windows 上是 16 位数字,在 Linux 上可以是字符串 - 接口名称,我没有找到接口名称的最大长度。

【讨论】:

【参考方案3】:

ipv6 地址可能有 46 个字符。

参考: IPv4 映射的 IPv6 地址 混合双栈 IPv6/IPv4 实现识别一类特殊的地址,即 IPv4 映射的 IPv6 地址。在这些地址中,前 80 位为零,接下来的 16 位为 1,其余 32 位是 IPv4 地址。人们可能会看到这些地址的前 96 位以标准 IPv6 格式编写,其余 32 位以 IPv4 的习惯点十进制表示法编写。例如 ::ffff:192.0.2.128 表示 IPv4 地址 192.0.2.128。与 IPv4 兼容的 IPv6 地址的弃用格式是 ::192.0.2.128.[61]

【讨论】:

【参考方案4】:

您可以使用 VARBINARY(16) 以二进制格式存储 IPv6 地址。

需要使用这些数据的应用程序可以使用它们的 inet_pton/ntop 实现来操作这些数据,或者您可以安装一个像 http://labs.watchmouse.com/2009/10/extending-mysql-5-with-ipv6-functions/ 那样的 UDF

【讨论】:

【参考方案5】:

假设您没有附加任何网络信息(例如 LL 标识符、类或 CIDR 掩码),IPv4 地址最多为 15 个字符(4x3 数字+3 个句点),而 IPv6 地址最多可包含 39 个字符字符。

【讨论】:

【参考方案6】:

如果您将它们存储为字符串而不是位模式:

IPv4 地址由四个 3 位十进制字符和三个 . 分隔符组成,因此只需要 15 个字符,例如 255.255.255.255

IPv6 地址由八个 4 位十六进制字符和七个 : 分隔符组成,因此需要 39 个字符,例如 0123:4567:89ab:cdef:0123:4567:89ab:cdef

【讨论】:

【参考方案7】:

在数值上,IPv4 地址为 32 位长,而 IPv6 地址为 128 位长。因此,您需要至少 16 个字节的存储空间。

如果你存储的“字符串”是字节形式的地址编码,那么16就足够了。

【讨论】:

以上是关于将 IPv4、IPv6 地址存储为字符串的大小的主要内容,如果未能解决你的问题,请参考以下文章

如何将 IPV6 地址转换为 IPV4 地址?

如何批量验证字符串是有效的 IPv4 或 IPv6 地址?

Lua函数检查ipv4或ipv6或字符串

如何确定字符串是 C# 中的有效 IPv4 还是 IPv6 地址?

从包含IPv4和IPv6的Ruby字符串中获取IPv4?

IPv4和IPv6地址的存取