Javascript IP地址比较

问题描述 投票:0回答:1

在Python中,我使用netaddr包来轻松进行ip地址比较和排序操作。例如:

IPAddress('1.2.3.4') < IPAddress('3.4.5.6')
IPAddress('1.2.3.4') is in IPNetwork('1.0.0.0/8')

现在我需要在 Javascript 中做同样的事情,而且我不想重新发明轮子..

我找不到一个可以轻松进行类似比较的节点包。我发现一些(如netmask)非常可靠,但仅限 IPv4。我需要支持 IPv4 和 IPv6 比较。

所以,我的要求是:

  • 节点包
  • 支持解析 IPv4 和 IPv6 CIDR 和 IP 地址
  • 支持“比较”和“包含”操作
  • 经过充分测试
javascript networking ip-address
1个回答
0
投票

令我有点惊讶的是,四年过去了,这个问题还没有得到一个像样的答案。我曾经使用过其中一个,并且 lodash 和 ipaddr.js 之间的世界如此接近,因此我决定完成一个解决方案。它由 3.5 个部分组成并使用两个库。这可能看起来很繁重,但您可能已经有了 lodash,如果您需要对 IPv4 和 IPv6 地址进行排序,您可能已经可以从

ipaddr.js
中受益。

(我有点惊讶

ipaddr.js
还没有这方面的东西。如果人们喜欢这个并且没有人分享更好的解决方案,我愿意将其作为模块的增强提交)

TL/DR:

  1. 使用 npm
    ipaddr.js
    解析您的 IP 地址;产生可比较的零件 (
    xtets
    )
  2. 使用
    lodash.sortBy
    进行紧凑的多维排序
    1. 如果比较 inet4 和 inet6 地址,请使用
      family
      属性作为第一个
      iteratee
    2. 生成
      iteratees
      数组,以比较
      octets
      生成的
      parts
      ipaddr.js
      数组的连续元素。

实施

// support fns/vars
const iteratees = [];
const xtet = n => (addr => (addr.octets || addr.parts)[n]); 
for(let i=0; i<8; i++) iteratees.push(xtet(i));
// the actual IP address sort function
const sortAddrs = (addrs) => _.sortBy(addrs, [ 'family', ...iteratees ]);

// Example usage (100 < 2 in string sort)
const addrs = ['fed0:100::1', '10.100.0.1', 'fed0:2::1', '10.2.0.1'];
const parsed = addrs.map((a) => ipaddr.parse(a));
const sorted = sortAddrs(parsed);
console.log(sorted.map(a => a.toString()));
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ipaddr.js/2.1.0/ipaddr.min.js"></script>
讨论

ipaddr.js是一个强大的IP地址检查和操作库。第一步是解析地址。生成的对象具有

octets
(v4) 或
parts
(v6) 属性,这只是每个
xtet
的整数表示,最高阶在前。 (我可能刚刚创造了
xtet
,我不确定)。

lodash.sortBy 让您直接关注排序比较的每次迭代,从而简化了复杂的排序。它需要一个集合和一个“迭代者”列表。仅当两个对象在先前的迭代器上继续相等时才会调用后续的迭代器。

我首先对系列进行排序,b/c 将 v4 地址与 v6 地址进行比较是没有意义的(没有额外的上下文来指示它们应该如何排序)。因此,

'family'
是第一个“迭代者”。

接下来,我们给出

sortBy
一个比较连续 xtets 的迭代数组。我的代码生成了一个由 8 个小函数组成的数组,每个函数返回
octets
parts
的第 n 个元素。这些是可直接用于排序目的的整数。

可能有一种更紧凑的方法来生成该数组,但我想不出一种方法。在该系列中,将一个 xtet 与另一个进行比较就像将地址转换为单个大整数一样正确。

注意:如果省略

family
迭代器,它似乎不会崩溃。然而我不认为结果有意义; v4 地址的第一个八位字节几乎总是小于 v6 地址的第一个十六进制,除了环回等极端情况。

© www.soinside.com 2019 - 2024. All rights reserved.