IP地址,因爲我們知道他們是簡單的32位數字值的字符串表示。
通過轉換字符串表示回其數字值,變得十分容易的範圍內使用本機數字比較地址的內檢查成員,如在下面的代碼:
var atoi = function atoi(addr) {
var parts = addr.split('.').map(function(str) {
return parseInt(str);
});
return (parts[0] ? parts[0] << 24 : 0) +
(parts[1] ? parts[1] << 16 : 0) +
(parts[2] ? parts[2] << 8 : 0) +
parts[3];
};
var checkIpaddrInRange = function checkIpaddrInRange(ipaddr, start, end) {
var num = atoi(ipaddr);
return (num >= atoi(start)) && (num <= atoi(end));
}
checkIpaddrInRange('10.0.1.1', '10.0.0.1', '10.0.2.1'); // => true
checkIpaddrInRange('10.0.3.1', '10.0.0.1', '10.0.2.1'); // => false
參見fiddle。
下面是同樣的事情,完全註釋和正確的錯誤檢查:
/**
* Checks if ipaddr is valid.
* @property {string} ipaddr
* @throws Error
*/
var assertIsIpaddr = function assertIsIpaddr(ipaddr) {
if('string' !== typeof ipaddr && ipaddr) {
throw new Error('ipaddr must be a non-empty string');
}
var parts=ipaddr.split(/\./);
if(parts.length !== 4){
throw new Error('ipaddr must have four octets');
}
var i=0;
parts.map(function(str){
var val=parseInt(str),
octet = 4 - i++;;
if(val < 0 || val > 255){
throw new Error('octet '+octet+' must be between 0 and 255');
}
});
};
/**
* Converts an ipaddr to a 32bit integer value.
* @property {string} addr - the ipaddr to convert
* @returns {number}
*/
var atoi = function atoi(addr) {
// test for validity - will throw!
assertIsIpaddr(addr);
// convert octets to numbers
var parts = addr.split('.').map(function(str) {
return parseInt(str);
});
// construct result
var result = (parts[0] ? parts[0] << 24 : 0) + // if > 0, shift 4th octet left by 24
(parts[1] ? parts[1] << 16 : 0) + // if > 0, shift 3rd octet left by 16
(parts[2] ? parts[2] << 8 : 0) + // if > 0, shift 2nd octet left by 8
parts[3];
// note that if all octets are 255, result will overflow
// JavaScript (32bit) number to become -1, so we have to
// special case it. I think throwing an error here is a
// reasonable solution, since 255.255.255.255 is actually
// a broadcast addr.
if(result < 0) {
throw new Error('255.255.255.255 is not a legal host ipaddr');
}
return result;
};
/**
* Checks ipaddr membership within a range of ipaddrs.
* @property {string} ipaddr - ipaddr to check
* @property {string} start - the start of the ipaddr range
* @property {string} end - the end of the ipaddr range
* @returns {boolean} - true if ipaddr is between start and end (inclusive)
*/
var checkIpaddrInRange = function checkIpaddrInRange(ipaddr, start, end) {
var num = atoi(ipaddr);
return (num >= atoi(start)) && (num <= atoi(end));
}
// OK, test it out...
checkIpaddrInRange('10.0.1.1','10.0.0.1','10.0.2.1'); // => true
checkIpaddrInRange('10.0.3.1','10.0.0.1','10.0.2.1'); // => false
你爲什麼從CIDR轉換了嗎? CIDR是位掩碼,允許您比較前N位,這與您將獲得的效率大致相同。 – ssube
當然。其實我已經想了一下。 CIDR作爲字符串輸入。這是一個掩碼的問題,或者我應該只是轉換爲數字? –
假設你只是處理IPv4地址,只需將地址轉換爲32位整數並進行比較。 –