Flutter如何连接WiFi Direct打印机并实现跨IP段外设扫描
跨网段局域网外设扫描实现方案
问题根源
- 你当前使用的lan_scanner默认仅扫描传入IP对应的子网段,不同网段的设备自然无法被识别
- printing包能找到跨网段打印机的原因是它采用了mDNS/SSDP这类局域网服务发现协议,而非单纯的同网段ICMP ping扫描
第一步:先修复现有代码的异步逻辑bug
你当前的searchDevices是异步方法,调用后直接使用wifiIP会出现空值,因为异步操作还未完成,需要先调整这部分逻辑。
第二步:跨网段扫描实现方案
方案1:多网段轮询扫描(适合明确知道目标网段范围的场景)
手动维护需要扫描的内网网段列表,依次扫描每个网段的所有IP,合并扫描结果,核心修改逻辑如下:
// 定义需要扫描的所有目标网段 List<String> targetSubnets = ['192.168.1', '192.168.10', '192.168.0']; void searchDevices() async { wifiIP = await NetworkInfo().getWifiIP(); // 自动提取当前WiFi网段加入扫描列表 String currSubnet = wifiIP!.substring(0, wifiIP!.lastIndexOf('.')); if(!targetSubnets.contains(currSubnet)){ targetSubnets.add(currSubnet); } // 启动多网段扫描 scanAllSubnets(); } void scanAllSubnets() async { for (String subnet in targetSubnets) { // 构造当前网段的示例IP传给扫描器 String sampleIp = '$subnet.1'; var stream = scanner.preciseScan( sampleIp, progressCallback: (ProgressModel progress) { print('扫描网段$subnet: ${(progress.percent * 100).toInt()}%'); }, ); await for (DeviceModel device in stream) { if (device.exists) { setState(() { hosts.add(device); }); } } } }
对应修改FloatingActionButton的onPressed逻辑,直接触发searchDevices即可,不用在方法外操作扫描逻辑。
方案2:服务发现扫描(适合未知网段、通用外设扫描场景)
和printing包实现逻辑一致,使用mDNS服务扫描,不需要关心网段,只要路由可达就能发现设备,扫描效率远高于轮询多网段,核心实现如下:
import 'package:multicast_dns/multicast_dns.dart'; void scanDevicesViaMDNS() async { // 可根据你要扫描的外设类型替换服务标识,_ipp._tcp.local为通用打印机服务标识 const String serviceType = '_ipp._tcp.local'; final MDnsClient client = MDnsClient(); await client.start(); await for (PtrResourceRecord ptr in client.lookup<PtrResourceRecord>(ResourceRecordQuery.serverPointer(serviceType))) { await for (SrvResourceRecord srv in client.lookup<SrvResourceRecord>(ResourceRecordQuery.service(ptr.domainName))) { // 获取设备IP信息 await for (ARecord ipRecord in client.lookup<ARecord>(ResourceRecordQuery.addressIPv4(srv.target))) { print('发现设备:${ipRecord.address}:${srv.port},设备名:${ptr.domainName}'); // 自行封装后加入设备列表即可 } } } client.stop(); }
注意事项
- 多网段扫描耗时会随网段数量线性增加,可以调整lan_scanner的timeout参数减少等待时间
- 需要提前申请对应平台的网络权限:Android端需添加
ACCESS_NETWORK_STATE、INTERNET权限,iOS端需开启本地网络权限
内容的提问来源于stack exchange,提问作者Jungwon
相关产品推荐
相关产品推荐

