Dart 实现 CIDR 详细信息获取
最近在使用 Flutter 开发APP,有个功能需要解析 CIDR 详细信息,所以就是要 dart 写了一段.
CIDR 示例
192.168.1.3/27
解析要求
解析出 可用地址数,起始地址,结束地址,子网掩码,网络地址,广播地址。
代码如下
import 'dart:math';
///
/// [CidrCalculator] can be used to fetch summary information for CIDR address like "192.168.0.2/22".
///
class CidrCalculator {
static const String PATTERN = r'^(?:'
r'(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([1-9]|[1-2]\d|3[0-2])$';
static bool isValid(String cidr) {
return RegExp(PATTERN).hasMatch(cidr);
}
/// parse cidr address info
static CidrInfo parse(String cidr) {
if (!isValid(cidr)) {
throw Exception("CIDR $cidr is invalid.");
}
int _maskLength;
String _mask;
String _ip;
String _network;
String _broadcast;
String _first;
String _last;
int _available;
/// get mask from mask length
String getMaskCodeFromMaskLength(int length) {
String maskBinary = '1' * length + '0' * (32 - length);
return int.parse(maskBinary.substring(0, 8), radix: 2).toString() +
'.' +
int.parse(maskBinary.substring(8, 16), radix: 2).toString() +
'.' +
int.parse(maskBinary.substring(16, 24), radix: 2).toString() +
'.' +
int.parse(maskBinary.substring(24, 32), radix: 2).toString();
}
/// split address by dot
List<String> splitAddress(String ipAddress) {
return ipAddress.split(r'.');
}
/// convert to bin list
List<String> convertToBinaryArray(List<String> array) {
for (int i = 0; i < array.length; i++) {
array[i] = (int.parse(array[i]) + 256).toRadixString(2).substring(1);
}
return array;
}
/// get network ID
String getNetworkId() {
List<String> ipArr = splitAddress(_ip);
List<String> maskArr = splitAddress(_mask);
List<String> networkArr = List(4);
for (int i = 0; i < 4; i++) {
networkArr[i] =
(int.parse(ipArr[i]) & int.parse(maskArr[i])).toString();
}
String networkId = networkArr.join('.');
return networkId;
}
/// get network broadcast address
String getNetworkBroadcast() {
List<String> maskArr = splitAddress(_mask);
List<String> networkIdArr = splitAddress(_network);
String maskBinaryString = convertToBinaryArray(maskArr).join(r'.');
int hostIndexOfMask = maskBinaryString.indexOf(r'0');
String networkIdBinaryString =
convertToBinaryArray(networkIdArr).join(r'.');
String netAddressOfNetwork =
networkIdBinaryString.substring(0, hostIndexOfMask);
String hostOfNetwork = networkIdBinaryString
.substring(hostIndexOfMask, networkIdBinaryString.length)
.replaceAll(RegExp(r'\d'), '1');
List<String> broadcastStringArr =
(netAddressOfNetwork + hostOfNetwork).split(r'.');
for (int i = 0; i < 4; i++) {
broadcastStringArr[i] =
int.parse(broadcastStringArr[i], radix: 2).toString();
}
return broadcastStringArr.join(r'.');
}
/// get first host in cidr
String getNetworkStart() {
List<String> networkIdArr = splitAddress(_network);
networkIdArr[3] = (int.parse(networkIdArr[3]) + 1).toString();
return networkIdArr.join('.');
}
/// get last host in cidr
String getNetworkEnd() {
List<String> broadcastArr = splitAddress(_broadcast);
broadcastArr[3] = (int.parse(broadcastArr[3]) - 1).toString();
return broadcastArr.join('.');
}
_maskLength = int.parse(cidr.substring(cidr.indexOf(r'/') + 1));
_ip = cidr.substring(0, cidr.indexOf(r'/'));
_mask = getMaskCodeFromMaskLength(_maskLength);
_network = getNetworkId();
_broadcast = getNetworkBroadcast();
_first = getNetworkStart();
_last = getNetworkEnd();
_available = pow(2, 32 - _maskLength) - 2;
return CidrInfo(
mask: _mask,
network: _network,
broadcast: _broadcast,
first: _first,
last: _last,
available: _available,
);
}
}
class CidrInfo {
/// netmask
final String mask;
/// Subnet ID
final String network;
/// broadcast address
final String broadcast;
/// first host address
final String first;
/// last host address
final String last;
/// available host addresses
final int available;
const CidrInfo({
this.mask,
this.network,
this.broadcast,
this.first,
this.last,
this.available,
});
@override
String toString() {
return "mask: $mask\nnetwork: $network\nbroadcast: $broadcast\nfirst: "
"$first\nlast: $last\navailable: $available";
}
}
使用示例
CidrInfo cidrInfo = CidrCalculator.parse("192.168.1.3/27");
print(cidrInfo);
输出
mask: 255.255.255.224
network: 192.168.1.0
broadcast: 192.168.1.31
first: 192.168.1.1
last: 192.168.1.30
available: 30
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。