最近开发中,经常出现attach失败,经过阅读源码和查阅资料,总算弄清楚了问题的原因。
第一种There are multiple observatory ports available.
➜ flutter attach
There are multiple observatory ports available.
Rerun this command with one of the following passed in as the appId:
flutter attach --app-id com.xxx.xxx (2)
flutter attach --app-id com.xxx.xxx
错误提示有两个app,使用 -v 看看
➜ flutter attach -v
There are multiple observatory ports available.
Rerun this command with one of the following passed in as the appId:
flutter attach --app-id com.xxx.xxx (2)
flutter attach --app-id com.xxx.xxx
#0 throwToolExit (package:flutter_tools/src/base/common.dart:28:3)
#1 MDnsObservatoryDiscovery.query (package:flutter_tools/src/mdns_discovery.dart:93:9)
#2 MDnsObservatoryDiscovery.getObservatoryUri (package:flutter_tools/src/mdns_discovery.dart:145:57)
#3 AttachCommand._attachToDevice (package:flutter_tools/src/commands/attach.dart:237:51)
从stack中我们发现MDnsObservatoryDiscovery中抛出了异常。mDNS是个什么东西?
第二种卡很久没有响应
Connecting to service protocol: http://127.0.0.1:63743/
[ +16 ms] Exception attempting to connect to Observatory: SocketException: OS Error: Connection refused,
errno = 61, address = 127.0.0.1, port = 56515
[ +5 ms] This was attempt #1. Will retry in 0:00:00.100000.
[ +106 ms] Exception attempting to connect to Observatory: SocketException: OS Error: Connection refused,
errno = 61, address = 127.0.0.1, port = 56516
[ +1 ms] This was attempt #2. Will retry in 0:00:00.200000.
[ +207 ms] Exception attempting to connect to Observatory: SocketException: OS Error: Connection refused,
errno = 61, address = 127.0.0.1, port = 56517
[ +1 ms] This was attempt #3. Will retry in 0:00:00.400000.
mDNS 协议 DNS-SD协议
参考 网络发现
原理
从上面的链接中可以了解到,flutter attach通过mDNS来查询调试设备的地址和端口,之后通过http进行通信。
错误分析
第一种
局域网内有两个设备注册了相同的服务,flutter attach在查询的时候发现了两个,直接抛异常
第二种
局域网内查询的时候查到了别人的服务,获取到错误的端口和authCode,导致连接不上。
解决办法
从原理中我们知道,如果能保证mDNS查询正确,那么attach就能成功。
直接指定地址
engine启动后log中会输出Observatory listening url,可以
flutter attach --debug-uri=you_observatory_listening_url
断网
从flutter 的源码中发现模拟器监听是127.0.0.1的地址,如果我们把外界的干扰断开,那就可以成功attach了,所以采取的办法就是断网
自动获取(iOS、MacOS)
每次从log复制地址还是有点麻烦,可以利用粘贴板来简化
engine启动后把url复制到粘贴板中,命令行读取粘贴板
[[UIPasteboard generalPasteboard] setURL:engine.observatoryUrl];
flutter attach --debug-uri=`pbpaste`
命令行模拟查询过程
注册
dns-sd -R com.xxx.xxx _dartobservatory._tcp local 63743 authCode=fdsafds
浏览 PTR
dns-sd -B _dartobservatory._tcp
SRV
dns-sd -L com.xxx.xxx _dartobservatory._tcp local