【问题标题】:How to generate random IPv4 number for a given country?如何为给定国家生成随机 IPv4 号码?
【发布时间】:2018-10-27 06:40:56
【问题描述】:

拥有给定国家/地区的 IPv4 地址范围,如何生成随机地址?例如,新加坡当前的一组范围(多个范围之一)是:

+----------+----------+--------------+
| ip_from  | ip_to    | country_code |
+----------+----------+--------------+
| 18925568 | 18926079 | SG           |
+----------+----------+--------------+

source: lite.ip2location.com

FAQ(3) 解释说

IP_Number = 16777216*w + 65536*x + 256*y + z

在哪里

IP_Address = w.x.y.z

IP_Number 代表ip_fromip_to。对于上面介绍的新加坡范围,它给了我:

16777216*w + 65536*x + 256*y + z >= 18925568; // from
16777216*w + 65536*x + 256*y + z <= 18926079; // to

如何生成随机的wxyz

【问题讨论】:

  • 在范围内生成一个随机数,然后重复 div/mod by 256。
  • div/mod by 256 重复然后验证 ip(不应以 0 或 255 结尾)。
  • IP 地址不是按国家/地区分配的。

标签: algorithm ip-address ipv4


【解决方案1】:

这是一个可测试的实现(在 JavaScript 中,因为它可以直接在这里运行)和一点描述。

首先您需要从指定范围内生成随机数。如果你有一个函数(我们称之为random)生成0到0.999之间的随机实数...[0,1)那么你可以这样做。

num = (random() * (end - start + 1)) + start

然后您需要使用mod 256 4 次将数字分成4 部分,并在给定数字上使用div 256 3 次(第四个div 操作是不必要的,但如果我们在循环中执行它那么为了简单起见,我们可以将其保留在那里,因为它不会改变任何事情)。

(% - modulo, // - div)

first = num % 256
num = num // 256

second = num % 256
num = num // 256

third = num % 256
num = num // 256

fourth = num % 256

然后您可以将它们推入数组[fourth, third, second, first](注意此处的顺序)并进行一些验证 - 一些地址是为私人互联网保留的,因此如果您碰巧生成其中一个,只需扔掉它并生成一个新的(你可以在这里循环或递归,直到你生成一个有效的)。

根据 RFC 1918 保留这些范围内的 IP 地址:

10.0.0.0        -   10.255.255.255  (10/8 prefix)
172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
192.168.0.0     -   192.168.255.255 (192.168/16 prefix) 

这是实现。

const start = 18925568;
const end = 18926079;

function _generateRandomIp(start, end) {
  let r = Math.floor(Math.random() * (end - start + 1)) + start;

  const ip = [];
  for (let i = 0; i < 4; i++) {
    ip.push(r % 256);
    r = Math.floor(r / 256);
  }

  return ip.reverse(); // put the results mod/div into correct order
}

function generateRandomIp(start, end) {
  let ip = _generateRandomIp(start, end);
  let valid = true;

  // ip can't be of format 10.xxx.xxx.xxx
  if (ip[0] === 10) { valid = false; }

  // ip can't be of format 172.16.xxx.xxx
  if (ip[0] === 172 && ip[1] === 16) { valid = false; }

  // ip can't be of format 192.168.xxx.xxx
  if (ip[0] === 192 && ip[1] === 168) { valid = false; }

  if (valid === true) {
    return ip.join('.'); // convert ip to string format
  } else {
    return generateRandomIp(start, end); // try again
  }
}

const ip = generateRandomIp(start, end);
console.log(ip);

上面的sn-p每次运行都会在那个范围内生成一个随机的ip地址。

这是您提到的页面中的测试用例,它说数字3401190660应该转换为202.186.13.4,所以让我们为这个随机生成的数字切换并尝试一下。

const start = 18925568;
const end = 18926079;

function _generateRandomIp(start, end) {
  let r = 3401190660; // here is that specific number

  const ip = [];
  for (let i = 0; i < 4; i++) {
    ip.push(r % 256);
    r = Math.floor(r / 256);
  }

  return ip.reverse(); // put the results mod/div into correct order
}

function generateRandomIp(start, end) {
  let ip = _generateRandomIp(start, end);
  let valid = true;

  // ip can't be of format 10.xxx.xxx.xxx
  if (ip[0] === 10) { valid = false; }

  // ip can't be of format 172.16.xxx.xxx
  if (ip[0] === 172 && ip[1] === 16) { valid = false; }

  // ip can't be of format 192.168.xxx.xxx
  if (ip[0] === 192 && ip[1] === 168) { valid = false; }

  if (valid === true) {
    return ip.join('.'); // convert ip to string format
  } else {
    return generateRandomIp(start, end); // try again
  }
}

const ip = generateRandomIp(start, end);
console.log(ip);

正如我们所见,这个算法产生了正确的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-09
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    相关资源
    最近更新 更多