Flutter端口扫描插件dart_port_scanner的使用
Flutter端口扫描插件dart_port_scanner的使用
dart_port_scanner
是一个简单而快速的TCP和UDP端口扫描器插件。本文将介绍如何在Flutter应用中使用该插件进行端口扫描,并提供完整的示例代码。
使用方法
TcpScannerTask
TcpScannerTask
允许异步执行扫描任务,并提供了基本的方法来控制任务。你可以通过设置 shuffle
参数为 true
来打乱端口顺序,默认情况下,套接字连接超时时间为2秒。如果在此时间内未收到响应,则端口将被标记为 closed
。你可以通过设置 socketTimeout
选项来更改此值,默认值为1000毫秒。你还可以通过定义 parallelism
选项指定要使用的隔离数,默认值为4。
示例代码
以下是一个简单的TCP端口扫描任务示例:
import 'dart:async';
import 'package:dart_port_scanner/dart_port_scanner.dart';
void main() async {
final host = 'mfazrinizar.com';
final ports = List.generate(990, (i) => 10 + i)
..add(5000)
..addAll([1100, 1110]);
var stopwatch = Stopwatch();
stopwatch.start();
try {
await TcpScannerTask(host, ports, shuffle: true, parallelism: 2)
.start()
.then((report) => print('Host ${report.host} scan completed\n'
'Scanned ports:\t${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch.elapsed}\n'))
// 捕获扫描期间的错误
.catchError((error) => stderr.writeln(error));
} catch (e) {
// 在构造函数中捕获异常
stderr.writeln('Error: $e');
}
}
UdpScannerTask
UdpScannerTask
类似于 TcpScannerTask
,但用于UDP端口扫描。默认情况下,套接字连接超时时间为1秒。如果在此时间内未收到响应,则端口将被标记为 filtered
。你可以通过设置 socketTimeout
选项来更改此值,默认值为1000毫秒。
示例代码
以下是一个简单的UDP端口扫描任务示例:
import 'dart:async';
import 'package:dart_port_scanner/dart_port_scanner.dart';
void main() async {
final host = 'mfazrinizar.com';
final ports = List.generate(990, (i) => 10 + i)
..add(5000)
..addAll([1100, 1110]);
var stopwatch = Stopwatch();
stopwatch.start();
try {
await UdpScannerTask(host, ports, shuffle: true, parallelism: 2)
.start()
.then((report) => print('Host ${report.host} scan completed\n'
'Scanned ports:\t${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch.elapsed}\n'))
// 捕获扫描期间的错误
.catchError((error) => stderr.writeln(error));
} catch (e) {
// 在构造函数中捕获异常
stderr.writeln('Error: $e');
}
}
取消任务和获取进度报告
你可以使用 cancel()
方法取消任务,它返回一个带有扫描结果的Future。请注意,在取消任务后,start()
方法的Future将不会返回任何结果。
你可以使用 report
字段在扫描期间请求状态更新。以下是一个示例,展示如何定期获取扫描进度报告:
var ports = List.generate(65535, (i) => 0 + i);
var stopwatch3 = Stopwatch();
stopwatch3.start();
try {
var scannerTask2 = TcpScannerTask(host, ports, parallelism: 100);
Timer.periodic(Duration(seconds: 1), (timer) {
scannerTask2.report.then((report) {
var percents = 100.0 * (report.openPorts.length + report.closedPorts.length) / report.ports.length;
var scanned = report.closedPorts.length + report.openPorts.length;
print('Host $host scan progress ${percents.toStringAsFixed(1)}%\n'
'Scanned ports:\t$scanned of ${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch3.elapsed}\n');
if (report.status == PortScannerTaskReportStatus.finished) {
timer.cancel();
}
});
});
await scannerTask2.start();
} catch (error) {
stderr.writeln(error);
}
完整示例
以下是一个完整的示例,展示如何根据用户输入选择不同的扫描类型(TCP、UDP、STCP、SUDP)并执行相应的扫描任务:
import 'dart:async';
import 'dart:io';
import 'package:dart_port_scanner/dart_port_scanner.dart';
enum ScanType { tcp, udp, stcp, sudp }
void main() async {
print(
"Enter 'TCP', 'UDP', 'STCP', or 'SUDP' ('S' stands for single) to start the scanner: ");
String? input = stdin.readLineSync();
if (input != null) {
ScanType? scanType = _parseScanType(input);
if (scanType != null) {
try {
switch (scanType) {
case ScanType.tcp:
await _performScan(
host: 'mfazrinizar.com',
ports: List.generate(1000, (i) => 10 + i)
..add(5000)
..addAll([1100, 1110]),
scannerTask: (host, ports, shuffle, parallelism, timeout) =>
TcpScannerTask(host, ports,
shuffle: shuffle,
parallelism: parallelism,
socketTimeout: timeout),
shuffle: true,
parallelism: 2,
timeout: Duration(milliseconds: 10),
);
break;
case ScanType.udp:
await _performScan(
host: 'mfazrinizar.com',
ports: List.generate(1000, (i) => 10 + i)
..add(5000)
..addAll([1100, 1110]),
scannerTask: (host, ports, shuffle, parallelism, timeout) =>
UdpScannerTask(host, ports,
shuffle: shuffle,
parallelism: parallelism,
socketTimeout: timeout),
shuffle: true,
parallelism: 2,
timeout: Duration(milliseconds: 1000),
);
break;
case ScanType.stcp:
await _performSingleScan(
host: 'mfazrinizar.com',
ports: [80, 443, 25565],
scannerTask: (host, ports, shuffle, parallelism, timeout) =>
TcpScannerTask(host, ports,
shuffle: shuffle,
parallelism: parallelism,
socketTimeout: timeout),
shuffle: true,
parallelism: 4,
timeout: Duration(milliseconds: 10000),
);
break;
case ScanType.sudp:
await _performSingleScan(
host: 'mfazrinizar.com',
ports: [25566, 25565],
scannerTask: (host, ports, shuffle, parallelism, timeout) =>
UdpScannerTask(host, ports,
shuffle: shuffle,
parallelism: parallelism,
socketTimeout: timeout),
shuffle: false,
parallelism: 1,
timeout: Duration(milliseconds: 5000),
);
break;
}
} catch (e) {
print("Error caught: ${e.toString()}");
}
} else {
print("Invalid input. Please enter 'TCP', 'UDP', 'STCP', or 'SUDP'.");
}
}
}
// 解析用户输入的扫描类型
ScanType? _parseScanType(String input) {
switch (input.toUpperCase()) {
case "TCP":
return ScanType.tcp;
case "UDP":
return ScanType.udp;
case "STCP":
return ScanType.stcp;
case "SUDP":
return ScanType.sudp;
default:
return null;
}
}
typedef ScannerTask = dynamic Function(String host, List<int> ports,
bool shuffle, int parallelism, Duration timeout);
// 执行扫描任务
Future<void> _performScan({
required String host,
required List<int> ports,
required ScannerTask scannerTask,
required bool shuffle,
required int parallelism,
required Duration timeout,
}) async {
var stopwatch1 = Stopwatch()..start();
// 简单扫描
try {
print('Starting simple scan...');
await scannerTask(host, ports, shuffle, parallelism, timeout)
.start()
.then((report) {
print('Host ${report.host} scan completed\n'
'Scanned ports:\t${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Closed ports:\t${report.closedPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch1.elapsed}\n');
}).catchError((error) => stderr.writeln(error));
} catch (e) {
stderr.writeln('Error: $e');
}
// 通过延迟取消扫描
var stopwatch2 = Stopwatch()..start();
try {
print('Starting scan with cancellation...');
var scannerTask1 = scannerTask(host, ports, shuffle, parallelism, timeout);
Future.delayed(Duration(seconds: 2), () {
print('ScannerTask cancelled by timeout after ${stopwatch2.elapsed}');
scannerTask1
.cancel()
.then((report) => print('Host ${report.host} scan was cancelled\n'
'Scanned ports:\t${report.openPorts.length + report.closedPorts.length}\n'
'Open ports:\t${report.openPorts}\n'
'Closed ports:\t${report.closedPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch2.elapsed}\n'))
.catchError((error) => stderr.writeln(error));
});
await scannerTask1.start();
} catch (error) {
stderr.writeln(error);
}
// 获取扫描期间的报告
var stopwatch3 = Stopwatch()..start();
try {
print('Starting scan with periodic reports...');
var scannerTask2 = scannerTask(host, ports, shuffle, parallelism, timeout);
Timer.periodic(Duration(seconds: 1), (timer) async {
try {
var report = await scannerTask2.report;
var percents = 100.0 *
(report.openPorts.length + report.closedPorts.length) /
report.ports.length;
var scanned = report.closedPorts.length + report.openPorts.length;
print('Host $host scan progress ${percents.toStringAsFixed(1)}%\n'
'Scanned ports:\t$scanned of ${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Closed ports:\t${report.closedPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch3.elapsed}\n');
if (report.status == PortScannerTaskReportStatus.finished) {
timer.cancel();
}
} catch (e) {
stderr.writeln('Error retrieving report: $e');
timer.cancel();
}
});
await scannerTask2.start();
} catch (error) {
stderr.writeln(error);
}
}
// 执行单个端口扫描任务
Future<void> _performSingleScan({
required String host,
required List<int> ports,
required ScannerTask scannerTask,
required bool shuffle,
required int parallelism,
required Duration timeout,
}) async {
var stopwatch1 = Stopwatch()..start();
// 简单扫描
try {
print('Starting simple scan...');
await scannerTask(host, ports, shuffle, parallelism, timeout)
.start()
.then((report) {
print('Host ${report.host} scan completed\n'
'Scanned ports:\t${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Closed ports:\t${report.closedPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch1.elapsed}\n');
}).catchError((error) => stderr.writeln(error));
} catch (e) {
stderr.writeln('Error: $e');
}
// 通过延迟取消扫描
var stopwatch2 = Stopwatch()..start();
try {
print('Starting scan with cancellation...');
var scannerTask1 = scannerTask(host, ports, shuffle, parallelism, timeout);
Future.delayed(Duration(seconds: 2), () {
print('ScannerTask cancelled by timeout after ${stopwatch2.elapsed}');
scannerTask1
.cancel()
.then((report) => print('Host ${report.host} scan was cancelled\n'
'Scanned ports:\t${report.openPorts.length + report.closedPorts.length}\n'
'Open ports:\t${report.openPorts}\n'
'Closed ports:\t${report.closedPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch2.elapsed}\n'))
.catchError((error) => stderr.writeln(error));
});
await scannerTask1.start();
} catch (error) {
stderr.writeln(error);
}
// 获取扫描期间的报告
var stopwatch3 = Stopwatch()..start();
try {
print('Starting scan with periodic reports...');
var scannerTask2 = scannerTask(host, ports, shuffle, parallelism, timeout);
Timer.periodic(Duration(seconds: 1), (timer) async {
try {
var report = await scannerTask2.report;
var percents = 100.0 *
(report.openPorts.length + report.closedPorts.length) /
report.ports.length;
var scanned = report.closedPorts.length + report.openPorts.length;
print('Host $host scan progress ${percents.toStringAsFixed(1)}%\n'
'Scanned ports:\t$scanned of ${report.ports.length}\n'
'Open ports:\t${report.openPorts}\n'
'Closed ports:\t${report.closedPorts}\n'
'Filtered ports:\t${report.filteredPorts}\n'
'Status:\t${report.status}\n'
'Elapsed:\t${stopwatch3.elapsed}\n');
if (report.status == PortScannerTaskReportStatus.finished) {
timer.cancel();
}
} catch (e) {
stderr.writeln('Error retrieving report: $e');
timer.cancel();
}
});
await scannerTask2.start();
} catch (error) {
stderr.writeln(error);
}
}
以上是 dart_port_scanner
插件的基本用法和完整示例代码。你可以根据需要调整参数和逻辑以满足具体需求。
更多关于Flutter端口扫描插件dart_port_scanner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter端口扫描插件dart_port_scanner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter端口扫描插件dart_port_scanner
的示例代码。这个插件允许你在Flutter应用中执行端口扫描操作。
首先,确保你的Flutter项目已经添加了dart_port_scanner
依赖。在pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
dart_port_scanner: ^最新版本号 # 请替换为最新的版本号
然后运行flutter pub get
来安装依赖。
接下来,编写Flutter代码来使用这个插件。以下是一个简单的示例,展示如何扫描指定IP地址上的端口范围:
import 'package:flutter/material.dart';
import 'package:dart_port_scanner/dart_port_scanner.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String result = "";
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Port Scanner Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _scanPorts,
child: Text('Scan Ports'),
),
Text(result, style: TextStyle(fontSize: 18)),
],
),
),
),
);
}
Future<void> _scanPorts() async {
String ipAddress = "192.168.1.1"; // 替换为你想要扫描的IP地址
int startPort = 1;
int endPort = 1024;
setState(() {
result = "Scanning ports...";
});
try {
var scanner = PortScanner();
var openPorts = await scanner.scan(ipAddress, startPort, endPort);
setState(() {
result = "Open ports:\n" + openPorts.join("\n");
});
} catch (e) {
setState(() {
result = "Error: ${e.message}";
});
}
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮和一个文本显示区域。当用户点击按钮时,应用会开始扫描指定IP地址(在示例中是192.168.1.1
)上的端口范围(从1到1024)。扫描完成后,结果显示在文本区域中。
请注意:
-
权限:在真实应用中,特别是涉及到网络操作时,请确保你有适当的权限,尤其是在Android和iOS平台上。你可能需要在
AndroidManifest.xml
和Info.plist
中添加相应的权限声明。 -
IP地址和端口范围:在示例中,IP地址和端口范围被硬编码了。在实际应用中,你可能希望让用户能够输入这些值。
-
错误处理:示例中包含了基本的错误处理,但在生产环境中,你可能需要更详细的错误处理和用户反馈机制。
-
性能考虑:端口扫描可能会比较耗时,特别是在扫描大量端口时。考虑在后台线程中执行扫描操作,以避免阻塞UI线程。
希望这个示例对你有帮助!如果有其他问题,请随时提问。