Önerilen çözümlerle ilgili bir sorun yaşadım, kullanmak lookup
her zaman beklenen değeri döndürmüyor.
Bunun nedeni DNS önbelleğe alınmasıdır, aramanın değeri önbelleğe alınır ve bir sonraki denemede uygun bir arama yapmak önbelleğe alınan değeri geri verir. Elbette bu, bağlantınızı kaybederseniz ve ararsanızlookup
, önbelleğe alınmış değeri internetiniz varmış gibi döndürebilir ve tersine, lookup
null döndükten sonra internetinizi yeniden bağlarsanız, bunun süresi boyunca hala boş dönecektir. önbellek, şu anda internetiniz olsa bile birkaç dakika sürebilir.
TL; DR: lookup
şeyi iade etmek, mutlaka internetiniz olduğu anlamına gelmez ve herhangi bir şey iade etmemesi, mutlaka internetiniz olmadığı anlamına gelmez. Güvenilir değil.
Eklentiden ilham alarak aşağıdaki çözümü uyguladım 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;
}
Çağrının tamamlanması _checkInternetAccess
en fazla bir süre alır timeout
(burada 3 saniye) ve DNS'den herhangi birine ulaşabilirsek, diğerlerini beklemeden ilkine ulaşılır ulaşılmaz tamamlanacaktır (birine ulaşmak için İnternetin olduğunu biliyorum). Tüm aramalar_pingDns
paralel olarak yapılır.
Bir IPV4 ağında iyi çalışıyor gibi görünüyor ve bunu bir IPV6 ağında test edemediğimde (birine erişimim yok) yine de çalışması gerektiğini düşünüyorum. Aynı zamanda sürüm modu yapılarında da çalışıyor, ancak yine de bu çözümle ilgili herhangi bir sorun bulup bulmadıklarını görmek için uygulamamı Apple'a göndermem gerekiyor.
Ayrıca çoğu ülkede (Çin dahil) çalışmalıdır, eğer birinde çalışmıyorsa, hedef ülkenizden erişilebilen listeye bir DNS ekleyebilirsiniz.