Flutter Multicast DNS 包在鸿蒙平台的使用指南
Multicast DNS插件是一个Dart包,支持通过mDNS协议进行本地网络服务发现,兼容Bonjour和Avahi等技术。该插件适配鸿蒙平台,提供IPv4/IPv6支持、多种资源记录查询和缓存机制。安装需通过Git引入依赖,并在鸿蒙配置中添加网络权限。核心API包括MDnsClient类和资源记录查询方法,使用流程包括启动客户端、查询PTR/SRV记录和解析IP地址。插件支持自定义网络接口选
1. 插件介绍
1.1 功能概述
Multicast DNS 是一个 Dart 包,用于通过 mDNS(Multicast DNS)协议进行服务发现,支持 Bonjour 和 Avahi 等服务发现技术。该包允许 Flutter 应用程序在本地网络中发现和解析其他设备或服务,无需依赖传统的 DNS 服务器。
1.2 主要特性
- 支持 IPv4 和 IPv6 网络接口
- 实现 RFC 6762 中定义的 “One-Shot Multicast DNS Queries” 规范
- 支持多种资源记录类型查询
- 内置资源记录缓存机制
- 可配置的网络接口选择
1.3 鸿蒙平台支持
该自定义修改版本的 Multicast DNS 包已适配鸿蒙平台,支持在鸿蒙设备上进行 mDNS 服务发现和查询。
2. 安装与配置
2.1 Git 依赖引入
由于这是一个自定义修改版本的包,需要通过 Git 形式引入。在项目的 pubspec.yaml 文件中添加以下依赖:
dependencies:
multicast_dns:
git:
url: "https://gitcode.com/openharmony-tpc/flutter_packages.git"
path: "packages/multicast_dns"
2.2 鸿蒙平台权限配置
在鸿蒙平台上使用网络相关功能,需要配置相应的网络权限。修改 module.json5 文件:
{
"module": {
"name": "entry",
"type": "entry",
"description": "Flutter Multicast DNS Example",
"mainElement": "MainAbility",
"deviceTypes": ["phone", "tablet"],
"reqPermissions": [
{
"name": "ohos.permission.INTERNET",
"reason": "需要网络权限进行 mDNS 查询",
"usedScene": {
"abilities": ["MainAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.GET_WIFI_INFO",
"reason": "需要 WiFi 信息进行网络接口选择",
"usedScene": {
"abilities": ["MainAbility"],
"when": "inuse"
}
}
],
// ... 其他配置
}
}
3. API 调用示例
3.1 核心类介绍
MDnsClient
MDnsClient 是该包的核心类,用于执行 mDNS 查询操作。主要方法包括:
start(): 启动 mDNS 客户端,开始监听和发送查询stop(): 停止客户端,释放资源lookup<T>(): 执行特定类型的资源记录查询
ResourceRecordQuery
用于创建不同类型的资源记录查询,主要方法包括:
ResourceRecordQuery.serverPointer(name): 创建 PTR 记录查询ResourceRecordQuery.service(name): 创建 SRV 记录查询ResourceRecordQuery.addressIPv4(name): 创建 A 记录查询(IPv4 地址)ResourceRecordQuery.addressIPv6(name): 创建 AAAA 记录查询(IPv6 地址)
3.2 基本使用流程
下面是一个完整的使用示例,展示如何使用 Multicast DNS 包发现本地网络中的 Dart Observatory 服务:
import 'package:multicast_dns/multicast_dns.dart';
Future<void> discoverDartObservatory() async {
// 创建 MDnsClient 实例
final MDnsClient client = MDnsClient();
try {
// 启动客户端,默认监听所有 IPv4 网络接口
await client.start();
const String serviceName = '_dartobservatory._tcp.local';
// 1. 查询 PTR 记录获取服务实例
await for (final PtrResourceRecord ptr in client
.lookup<PtrResourceRecord>(ResourceRecordQuery.serverPointer(serviceName))) {
print('发现服务实例: ${ptr.domainName}');
// 2. 查询 SRV 记录获取服务端口和目标主机
await for (final SrvResourceRecord srv in client.lookup<SrvResourceRecord>(
ResourceRecordQuery.service(ptr.domainName))) {
print('服务地址: ${srv.target}:${srv.port}');
// 3. 查询 A 记录获取 IPv4 地址
await for (final IPAddressResourceRecord ipAddr in client
.lookup<IPAddressResourceRecord>(ResourceRecordQuery.addressIPv4(srv.target))) {
print('IPv4 地址: ${ipAddr.address}');
}
}
}
} catch (e) {
print('服务发现失败: $e');
} finally {
// 停止客户端,释放资源
client.stop();
}
}
3.3 高级配置选项
指定网络接口类型
可以通过 start() 方法的参数指定监听的网络接口类型:
// 只监听 IPv6 网络接口
await client.start(
listenAddress: InternetAddress.anyIPv6,
);
自定义网络接口工厂
可以自定义网络接口工厂来选择特定的网络接口:
Future<Iterable<NetworkInterface>> customInterfacesFactory(InternetAddressType type) async {
// 获取所有网络接口
final List<NetworkInterface> interfaces = await NetworkInterface.list(
includeLinkLocal: true,
type: type,
includeLoopback: false, // 排除回环接口
);
// 只返回 WiFi 接口
return interfaces.where((interface) => interface.name.contains('wlan'));
}
// 使用自定义网络接口工厂
await client.start(
interfacesFactory: customInterfacesFactory,
);
配置查询超时
可以为查询设置超时时间:
await for (final PtrResourceRecord ptr in client
.lookup<PtrResourceRecord>(
ResourceRecordQuery.serverPointer(serviceName),
timeout: Duration(seconds: 10), // 设置 10 秒超时
)) {
// 处理查询结果
}
4. 完整示例应用
下面是一个完整的鸿蒙 Flutter 应用示例,展示如何使用 Multicast DNS 包:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:multicast_dns/multicast_dns.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'mDNS 服务发现',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'mDNS 服务发现示例'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<String> _services = [];
bool _isScanning = false;
Future<void> _scanForServices() async {
setState(() {
_isScanning = true;
_services.clear();
});
final MDnsClient client = MDnsClient();
try {
await client.start();
// 查找所有 HTTP 服务
const String serviceName = '_http._tcp.local';
await for (final PtrResourceRecord ptr in client
.lookup<PtrResourceRecord>(ResourceRecordQuery.serverPointer(serviceName))) {
_services.add('发现服务: ${ptr.domainName}');
await for (final SrvResourceRecord srv in client.lookup<SrvResourceRecord>(
ResourceRecordQuery.service(ptr.domainName))) {
_services.add(' 地址: ${srv.target}:${srv.port}');
// 查询 IPv4 地址
await for (final IPAddressResourceRecord ipAddr in client
.lookup<IPAddressResourceRecord>(ResourceRecordQuery.addressIPv4(srv.target))) {
_services.add(' IPv4: ${ipAddr.address}');
}
}
}
if (_services.isEmpty) {
_services.add('未发现任何 HTTP 服务');
}
} catch (e) {
_services.add('扫描失败: $e');
} finally {
client.stop();
setState(() {
_isScanning = false;
});
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _isScanning ? null : _scanForServices,
child: _isScanning
? const CircularProgressIndicator()
: const Text('扫描本地 HTTP 服务'),
),
const SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: _services.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_services[index]),
);
},
),
),
],
),
),
);
}
}
5. 鸿蒙平台注意事项
5.1 网络权限
确保在 module.json5 文件中配置了必要的网络权限,否则应用可能无法正常进行 mDNS 查询。
5.2 网络环境
mDNS 协议依赖于本地网络的多播支持,请确保设备连接到支持多播的网络环境(通常是 WiFi 网络)。
5.3 性能考虑
- 避免频繁创建和销毁
MDnsClient实例,建议在应用生命周期内复用同一个实例 - 及时调用
stop()方法释放资源,避免内存泄漏 - 对于长时间运行的应用,可以定期清理资源记录缓存
5.4 兼容性
- 支持鸿蒙 API 9 及以上版本
- 兼容 Flutter 3.7.0 及以上版本
- 兼容 Dart 2.19.0 及以上版本
6. 总结
Flutter Multicast DNS 包为鸿蒙平台提供了强大的服务发现能力,允许应用程序在本地网络中发现和解析其他设备或服务。通过本文的介绍,您应该已经了解了如何:
- 以 Git 形式引入自定义修改版本的 Multicast DNS 包
- 配置鸿蒙平台所需的网络权限
- 使用 MDnsClient 类执行服务发现查询
- 处理不同类型的资源记录
- 实现完整的服务发现功能
该包在智能家居、本地网络应用、设备配对等场景中具有广泛的应用前景,能够帮助开发者构建更加智能和互联的鸿蒙应用程序。
更多推荐

所有评论(0)