제안 된 솔루션에 문제가 있었는데 사용 lookup
이 항상 예상 값을 반환하지는 않습니다.
이것은 DNS 캐싱으로 인한 것이며, 호출 값이 캐시되고 다음 시도에서 적절한 호출을 수행하도록 지시되어 캐시 된 값을 돌려줍니다. 물론 이것은 연결이 끊어지고 호출 lookup
하면 인터넷이있는 것처럼 캐시 된 값을 반환 할 수 있으므로 여기서 문제가됩니다. 반대로 lookup
null 을 반환 한 후 인터넷을 다시 연결 하면 계속해서 null을 반환합니다. 지금 인터넷에 연결되어 있어도 몇 분 정도 걸릴 수 있습니다.
요약 : lookup
무언가를 반환한다고해서 반드시 인터넷이 있다는 의미는 아니며 아무것도 반환하지 않는다고해서 반드시 인터넷이 없다는 의미는 아닙니다. 신뢰할 수 없습니다.
data_connection_checker
플러그인 에서 영감을 얻어 다음 솔루션을 구현했습니다 .
Future<bool> _checkInternetAccess() {
final List<InternetAddress> dnss = [
InternetAddress('8.8.8.8', type: InternetAddressType.IPv4),
InternetAddress('2001:4860:4860::8888', type: InternetAddressType.IPv6),
InternetAddress('1.1.1.1', type: InternetAddressType.IPv4),
InternetAddress('2606:4700:4700::1111', type: InternetAddressType.IPv6),
InternetAddress('208.67.222.222', type: InternetAddressType.IPv4),
InternetAddress('2620:0:ccc::2', type: InternetAddressType.IPv6),
InternetAddress('180.76.76.76', type: InternetAddressType.IPv4),
InternetAddress('2400:da00::6666', type: InternetAddressType.IPv6),
];
final Completer<bool> completer = Completer<bool>();
int callsReturned = 0;
void onCallReturned(bool isAlive) {
if (completer.isCompleted) return;
if (isAlive) {
completer.complete(true);
} else {
callsReturned++;
if (callsReturned >= dnss.length) {
completer.complete(false);
}
}
}
dnss.forEach((dns) => _pingDns(dns).then(onCallReturned));
return completer.future;
}
Future<bool> _pingDns(InternetAddress dnsAddress) async {
const int dnsPort = 53;
const Duration timeout = Duration(seconds: 3);
Socket socket;
try {
socket = await Socket.connect(dnsAddress, dnsPort, timeout: timeout);
socket?.destroy();
return true;
} on SocketException {
socket?.destroy();
}
return false;
}
에 대한 호출 _checkInternetAccess
은 timeout
완료 하는 데 최대 시간 (여기서는 3 초) 이 걸리며 , DNS에 도달 할 수있는 경우 다른 DNS를 기다리지 않고 첫 번째 DNS에 도달하자마자 완료됩니다 (하나에 도달하면 인터넷이 있다는 것을 알고 있습니다). 에 대한 모든 호출 _pingDns
은 병렬로 수행됩니다.
IPV4 네트워크에서 잘 작동하는 것 같고 IPV6 네트워크에서 테스트 할 수없는 경우 (액세스 권한이 없음) 여전히 작동해야한다고 생각합니다. 릴리스 모드 빌드에서도 작동하지만이 솔루션에서 문제가 있는지 확인하려면 아직 내 앱을 Apple에 제출해야합니다.
또한 대부분의 국가 (중국 포함)에서도 작동합니다. 하나에서 작동하지 않는 경우 대상 국가에서 액세스 할 수있는 목록에 DNS를 추가 할 수 있습니다.