从 JS 中的子网生成随机 IP 地址
Generate a random IP address from a subnet in JS
我正在尝试生成一个给定 IP 地址子网的随机 IP 地址。有很多资源可用于生成随机 IP,但我要求它是从特定子网内生成的。
我使用了一个名为 netmask 的 npm 模块 - 但是实现绝对不优雅。任何人都可以为此提供一些巧妙的指示吗?
var netmask = require("netmask").Netmask
var block = new netmask('10.0.0.0/24')
console.log(block) // gives block details
var blockSize = block.size - 1 ;
var randomIndex = Math.floor(Math.random() * blockSize ) +1; // generate a random number less than the size of the block
console.log("randomIndex is: " + randomIndex);
block.forEach(function(ip, long, index){
if(index == randomIndex){
console.log('IP: ' + ip)
console.log('INDEX: ' + index)
// cannot break! this is a forEach :(
}
});
这很简单,没有任何额外的依赖,虽然我没有给你一个确切的答案,但我想知道如何 IP's work in general 以及如何解决你的问题。如果您自己动手,这节课会更有价值。
我们以10.0.0.0/20
CIDR为例。让我们将 10.0.0.0
转换为位:
00001010.00000000.00000000.00000000
我们去掉 20 位,因为这是从左边开始的网络,所以我们剩下 0000.00000000
用于主机(.
点在这里只是为了便于阅读):
00001010.00000000.00000000.00000000 Network
XXXXXXXX.XXXXXXXX.XXXX0000.00000000 Strip 20 bits of the subnet
随心所欲地用剩余的位打乱每个八位组,例如我们可以得到 0101.10001010
。避免仅使用 1
s (1111.11111111
) 的主机,因为它是 broadcast IP,它仍然是一个有效的 IP,但不适用于主机。将子网部分与主机部分连接起来。我们得到:
// S=Subnet, H=Host
SSSSSSSS.SSSSSSSS.SSSSHHHH.HHHHHHHH
00001010.00000000.00000101.10001010
也就是1010 = 10
and 0
and 101 = 5
and 10001010=138
所以最后的地址是10.0.5.138
因为写起来很有趣,我可以给你我自己的实现,不涉及任何字符串操作。如您所见,IPv4 地址是一个 2^32
无符号整数。因此我们可以应用基础数学:
let ipv4 = {
random: function (subnet, mask) {
// generate random address (integer)
// if the mask is 20, then it's an integer between
// 1 and 2^(32-20)
let randomIp = Math.floor(Math.random() * Math.pow(2, 32 - mask)) + 1;
return this.lon2ip(this.ip2lon(subnet) | randomIp);
},
ip2lon: function (address) {
let result = 0;
address.split('.').forEach(function(octet) {
result <<= 8;
result += parseInt(octet, 10);
});
return result >>> 0;
},
lon2ip: function (lon) {
return [lon >>> 24, lon >> 16 & 255, lon >> 8 & 255, lon & 255].join('.');
}
};
// unit test
console.log(
"192.168.0.35" === ipv4.lon2ip(ipv4.ip2lon('192.168.0.35')) ?
'Test passed' :
'Test failed'
);
for (let i = 0; i < 5; i++) {
console.log(ipv4.random('10.0.0.0', 8));
}
基于 emix 的回答 -
function getIPFromSubnet(subnetRange) {
// subnetRange = "10.0.0.0/24"
const subnet = subnetRange.split('/')[0]; // 10.0.0.0
const mask = subnetRange.split('/')[1]; // 24
const ipArray = subnet.split('.'); //["10", "0", "0", "0"]
var ipInBinary = ""; // will contain the binary equivalent of the iP
// for each element in the array, convert from decimal to binary
for (let quad of ipArray) {
let octet = parseInt(quad, 10).toString(2)
// we need each octet to be 8 bits. So provide padding for those which are less than 8 bits
// 0101 becomes 00000101
let octetLength = octet.length
if (octetLength < 8) {
let octDiff = 8 - octetLength;
octet = "0".repeat(octDiff) + octet
}
// concat all the octets into a 32 bit binary
ipInBinary = ipInBinary.concat(octet) // 00001010000000000000000000000000
}
// console.log("ipInBinary: ", ipInBinary);
// strip the subnet from the entire address:
let subnetBinary = ipInBinary.slice(0, mask) // 000010100000000000000000
let hostsBinary = ipInBinary.slice(mask, ipInBinary.length) // 00000000
var randomBinarySubstitute = "";
const randomPool = "10101010101010101010101010101010" //fix this nonsense later.
for (let i = 0; i < 32 - mask; i++) {
randomBinarySubstitute += randomPool[Math.floor(Math.random() * ipInBinary.length)]
}
let newIPBinary = subnetBinary + randomBinarySubstitute;
let finalIP = "";
// split the 32 bit binary IP into an array of 8 bits, each representing an octate
let finalIPArray_binary = newIPBinary.match(/.{8}/g) // ["00001010", "00000000", "00000000", "10001010"]
// convert the binary quad array to decimal dotted quad
for (let element of finalIPArray_binary) {
finalIP = finalIP + "." + parseInt(element, 2);
finalIP = finalIP.replace(/^\./, ""); // remnove the leading .
}
console.log("FinalIP", finalIP)
return finalIP
}
getIPFromSubnet('10.0.0.0/16')
(我在等你 post 你自己的功能,然后 post 我的。)
这是我自己的版本,基于 emix 的回答。
我尝试使用循环和数组函数使其最容易理解。
第一个片段
// Function to convert string of numbers to 01010101 with leading zeros
function StrToBlock(str) {
return ("00000000" + (+str).toString(2)).slice(-8);
}
// Function to convert 01010101 to string of numbers
function BlockToStr(block) {
return parseInt(block, 2);
}
// Main function
function GetRandomIP(netmask) {
// Split netmask
var netmasks = netmask.split("/");
var maskBlocks = netmasks[0].split(".");
var maskLength = netmasks[1];
// Loop for each address part
var blockBits = '';
maskBlocks.forEach(function(block) {
// Convert to bits
blockBits = blockBits + StrToBlock(block);
});
// Here, blockBits is something like 00110101001101010011010100110101
// Loop for each bit
var ipBits = [];
var ipBlocks = [];
for (var i = 0; i < 32; i++) {
// If in mask, take the mask bit, else, a random 0 or 1
var bit = (i < maskLength) ? blockBits[i] : Math.round(Math.random());
ipBits.push(bit);
// If block is full, convert back to a decimal string
if (ipBits.length == 8) {
ipBlocks.push(BlockToStr(ipBits.join('')));
ipBits = []; // Erase to start a new block
}
}
// Return address as string
return ipBlocks.join('.');
}
// Different tests
console.log(GetRandomIP('255.255.255.0/8'));
console.log(GetRandomIP('255.255.255.0/24'));
console.log(GetRandomIP('10.0.0.0/24'));
⋅
⋅
⋅
第二个片段 (增强,在我看来)
// Function to convert string of numbers to 01010101 with leading zeros
function StrToBlock(str) {
return ("00000000" + (+str).toString(2)).slice(-8);
}
// Function to convert 01010101 to string of numbers
function BlockToStr(block) {
return parseInt(block, 2);
}
// Main function
function GetRandomIP(netmask) {
// Split netmask
var netmasks = netmask.split("/");
var maskBlocks = netmasks[0].split(".");
var maskLength = netmasks[1];
// Loop for each of the 4 address parts
var blockBits = '';
maskBlocks.forEach(function(block) {
blockBits = blockBits + StrToBlock(block);
});
// Copy mask and then add some random bits
var ipBits = blockBits.substring(0, maskLength);
for (var i = maskLength; i < 32; i++) {
ipBits = ipBits + Math.round(Math.random());
}
// Split and convert back to decimal strings
var ipBlocks = ipBits.match(/.{8}/g);
ipBlocks.forEach(function(block, i) {
ipBlocks[i] = BlockToStr(block);
});
// Return address as string
return ipBlocks.join('.');
}
// Different tests
console.log(GetRandomIP('255.255.255.0/8'));
console.log(GetRandomIP('255.255.255.0/24'));
console.log(GetRandomIP('10.0.0.0/24'));
我正在尝试生成一个给定 IP 地址子网的随机 IP 地址。有很多资源可用于生成随机 IP,但我要求它是从特定子网内生成的。
我使用了一个名为 netmask 的 npm 模块 - 但是实现绝对不优雅。任何人都可以为此提供一些巧妙的指示吗?
var netmask = require("netmask").Netmask
var block = new netmask('10.0.0.0/24')
console.log(block) // gives block details
var blockSize = block.size - 1 ;
var randomIndex = Math.floor(Math.random() * blockSize ) +1; // generate a random number less than the size of the block
console.log("randomIndex is: " + randomIndex);
block.forEach(function(ip, long, index){
if(index == randomIndex){
console.log('IP: ' + ip)
console.log('INDEX: ' + index)
// cannot break! this is a forEach :(
}
});
这很简单,没有任何额外的依赖,虽然我没有给你一个确切的答案,但我想知道如何 IP's work in general 以及如何解决你的问题。如果您自己动手,这节课会更有价值。
我们以10.0.0.0/20
CIDR为例。让我们将 10.0.0.0
转换为位:
00001010.00000000.00000000.00000000
我们去掉 20 位,因为这是从左边开始的网络,所以我们剩下 0000.00000000
用于主机(.
点在这里只是为了便于阅读):
00001010.00000000.00000000.00000000 Network
XXXXXXXX.XXXXXXXX.XXXX0000.00000000 Strip 20 bits of the subnet
随心所欲地用剩余的位打乱每个八位组,例如我们可以得到 0101.10001010
。避免仅使用 1
s (1111.11111111
) 的主机,因为它是 broadcast IP,它仍然是一个有效的 IP,但不适用于主机。将子网部分与主机部分连接起来。我们得到:
// S=Subnet, H=Host
SSSSSSSS.SSSSSSSS.SSSSHHHH.HHHHHHHH
00001010.00000000.00000101.10001010
也就是1010 = 10
and 0
and 101 = 5
and 10001010=138
所以最后的地址是10.0.5.138
因为写起来很有趣,我可以给你我自己的实现,不涉及任何字符串操作。如您所见,IPv4 地址是一个 2^32
无符号整数。因此我们可以应用基础数学:
let ipv4 = {
random: function (subnet, mask) {
// generate random address (integer)
// if the mask is 20, then it's an integer between
// 1 and 2^(32-20)
let randomIp = Math.floor(Math.random() * Math.pow(2, 32 - mask)) + 1;
return this.lon2ip(this.ip2lon(subnet) | randomIp);
},
ip2lon: function (address) {
let result = 0;
address.split('.').forEach(function(octet) {
result <<= 8;
result += parseInt(octet, 10);
});
return result >>> 0;
},
lon2ip: function (lon) {
return [lon >>> 24, lon >> 16 & 255, lon >> 8 & 255, lon & 255].join('.');
}
};
// unit test
console.log(
"192.168.0.35" === ipv4.lon2ip(ipv4.ip2lon('192.168.0.35')) ?
'Test passed' :
'Test failed'
);
for (let i = 0; i < 5; i++) {
console.log(ipv4.random('10.0.0.0', 8));
}
基于 emix 的回答 -
function getIPFromSubnet(subnetRange) {
// subnetRange = "10.0.0.0/24"
const subnet = subnetRange.split('/')[0]; // 10.0.0.0
const mask = subnetRange.split('/')[1]; // 24
const ipArray = subnet.split('.'); //["10", "0", "0", "0"]
var ipInBinary = ""; // will contain the binary equivalent of the iP
// for each element in the array, convert from decimal to binary
for (let quad of ipArray) {
let octet = parseInt(quad, 10).toString(2)
// we need each octet to be 8 bits. So provide padding for those which are less than 8 bits
// 0101 becomes 00000101
let octetLength = octet.length
if (octetLength < 8) {
let octDiff = 8 - octetLength;
octet = "0".repeat(octDiff) + octet
}
// concat all the octets into a 32 bit binary
ipInBinary = ipInBinary.concat(octet) // 00001010000000000000000000000000
}
// console.log("ipInBinary: ", ipInBinary);
// strip the subnet from the entire address:
let subnetBinary = ipInBinary.slice(0, mask) // 000010100000000000000000
let hostsBinary = ipInBinary.slice(mask, ipInBinary.length) // 00000000
var randomBinarySubstitute = "";
const randomPool = "10101010101010101010101010101010" //fix this nonsense later.
for (let i = 0; i < 32 - mask; i++) {
randomBinarySubstitute += randomPool[Math.floor(Math.random() * ipInBinary.length)]
}
let newIPBinary = subnetBinary + randomBinarySubstitute;
let finalIP = "";
// split the 32 bit binary IP into an array of 8 bits, each representing an octate
let finalIPArray_binary = newIPBinary.match(/.{8}/g) // ["00001010", "00000000", "00000000", "10001010"]
// convert the binary quad array to decimal dotted quad
for (let element of finalIPArray_binary) {
finalIP = finalIP + "." + parseInt(element, 2);
finalIP = finalIP.replace(/^\./, ""); // remnove the leading .
}
console.log("FinalIP", finalIP)
return finalIP
}
getIPFromSubnet('10.0.0.0/16')
(我在等你 post 你自己的功能,然后 post 我的。)
这是我自己的版本,基于 emix 的回答。
我尝试使用循环和数组函数使其最容易理解。
第一个片段
// Function to convert string of numbers to 01010101 with leading zeros
function StrToBlock(str) {
return ("00000000" + (+str).toString(2)).slice(-8);
}
// Function to convert 01010101 to string of numbers
function BlockToStr(block) {
return parseInt(block, 2);
}
// Main function
function GetRandomIP(netmask) {
// Split netmask
var netmasks = netmask.split("/");
var maskBlocks = netmasks[0].split(".");
var maskLength = netmasks[1];
// Loop for each address part
var blockBits = '';
maskBlocks.forEach(function(block) {
// Convert to bits
blockBits = blockBits + StrToBlock(block);
});
// Here, blockBits is something like 00110101001101010011010100110101
// Loop for each bit
var ipBits = [];
var ipBlocks = [];
for (var i = 0; i < 32; i++) {
// If in mask, take the mask bit, else, a random 0 or 1
var bit = (i < maskLength) ? blockBits[i] : Math.round(Math.random());
ipBits.push(bit);
// If block is full, convert back to a decimal string
if (ipBits.length == 8) {
ipBlocks.push(BlockToStr(ipBits.join('')));
ipBits = []; // Erase to start a new block
}
}
// Return address as string
return ipBlocks.join('.');
}
// Different tests
console.log(GetRandomIP('255.255.255.0/8'));
console.log(GetRandomIP('255.255.255.0/24'));
console.log(GetRandomIP('10.0.0.0/24'));
⋅ ⋅ ⋅
第二个片段 (增强,在我看来)
// Function to convert string of numbers to 01010101 with leading zeros
function StrToBlock(str) {
return ("00000000" + (+str).toString(2)).slice(-8);
}
// Function to convert 01010101 to string of numbers
function BlockToStr(block) {
return parseInt(block, 2);
}
// Main function
function GetRandomIP(netmask) {
// Split netmask
var netmasks = netmask.split("/");
var maskBlocks = netmasks[0].split(".");
var maskLength = netmasks[1];
// Loop for each of the 4 address parts
var blockBits = '';
maskBlocks.forEach(function(block) {
blockBits = blockBits + StrToBlock(block);
});
// Copy mask and then add some random bits
var ipBits = blockBits.substring(0, maskLength);
for (var i = maskLength; i < 32; i++) {
ipBits = ipBits + Math.round(Math.random());
}
// Split and convert back to decimal strings
var ipBlocks = ipBits.match(/.{8}/g);
ipBlocks.forEach(function(block, i) {
ipBlocks[i] = BlockToStr(block);
});
// Return address as string
return ipBlocks.join('.');
}
// Different tests
console.log(GetRandomIP('255.255.255.0/8'));
console.log(GetRandomIP('255.255.255.0/24'));
console.log(GetRandomIP('10.0.0.0/24'));