IPv6地址验证与规范化

5 投票
11 回答
18238 浏览
提问于 2025-04-15 14:07

你用过哪些库来处理这个问题?它们之间的兼容性怎么样?还是说你自己写了一个解析程序?

我特别想知道在Java、C++、Python和JavaScript中,有哪些相互兼容的实现,支持以下功能:

  • 零压缩(比如"::")
  • IPv4映射地址(像"::ffff:123.45.67.89")
  • 规范化(包括转换为简短形式,方便人类阅读)
  • CIDR风格的网络掩码(比如结尾的"/64")

11 个回答

5

在Java中,Guava库提供了一些实用的功能,可以用来验证IPv6(还有IPv4)地址,这些功能在com.google.common.net.InetAddresses这个类里。你可以在这里找到更多信息:http://goo.gl/RucRU

5

在Java中,你可以使用

InetAddress.getByName(IP)

然后检查这个过程中是否抛出了异常,以此来验证IPv6地址的有效性。

如果你觉得可以的话,也可以使用Sun的专有API。这个方法不会进行DNS查找。(因为这是他们的专有API,可能会在没有通知的情况下更改或删除。这是编写代码时会出现的一个警告。)

boolean sun.net.util.IPAddressUtil.isIPv6LiteralAddress(String IP)
7

在POSIX系统上,你可以使用inet_ptoninet_ntop这两个函数来进行标准化处理。不过,你还是需要自己解析CIDR(无类域间路由)格式。幸运的是,我认为IPv6的有效CIDR语法只有一种,就是用/后面跟位数的方式,这样比较简单。

另一个你可能会遇到的问题是对接口规范的支持不足。对于链路本地地址,你会看到像%eth0这样的后缀,用来指定它们是本地于哪个链路的。getaddrinfo可以解析这个,但inet_pton就不行了。

你可以考虑的一个策略是使用getaddrinfo来解析地址,然后用inet_ntop来进行标准化。

getaddrinfo在Windows上是可以用的,而inet_ptoninet_ntop则不支持。不过,写代码来生成标准的IPv6地址并不难。需要注意的是,这个过程要分两次进行,因为0压缩的规则是先出现的最长的0串。此外,IPv4格式(比如::127.0.0.1)只用于::IPv4::ffff:IPv4

我没有Windows机器来测试,但根据文档,Python在Windows上支持inet_ptoninet_ntop这两个函数。

自己写一个生成标准格式的函数可能是个不错的主意,因为即使你的标准格式和别人不一样,只要是有效的,其他人也能解析它。但我绝对不建议你自己写一个来解析IPv6地址的函数。

我上面的建议适用于Python、C和C++。至于Java或JavaScript,我几乎一无所知,不知道怎么解决这个问题。

编辑:我一直在研究getaddrinfo和它的对应函数getnameinfo。这两个函数在很多方面都比inet_ptoninet_ntop要好。它们是线程安全的,你可以传递一些选项(在getaddrinfo中是AI_NUMERICHOST,在getnameinfo中是NI_NUMERCHOST),这样就可以避免进行任何DNS查询。它们的接口有点复杂,有些地方让我想起了丑陋的Windows界面,但其实搞清楚该传什么选项来得到想要的结果还是比较简单的。我非常推荐这两个函数。

撰写回答