iOS: reachabilityWithHostname OUI bien qu'il devrait être NON

J'ai testé différents frameworks, par exemple

  • https://github.com/tonymillion/Reachability
  • https://github.com/VerticodeLabs/VCLReachability
  • https://github.com/kstenerud/KSReachability

et j'aimerais savoir si un hôte est joignable. Sur mon iPhone, je mets mon iMac en proxy (Charles) et bloque ou ne bloque pas les connections, mais l'accessibilité est toujours OUI. Seulement si je mets un hôte inexistant, il renvoie NON. Mais si l'hôte existe mais que je bloque la connection, je reçois toujours isReachable . N'y at-il pas un moyen de vérifier si l'hôte est vraiment accessible?

Si j'essaye avec KSReachability, je fais ce qui suit:

 self.reachability = [KSReachability reachabilityToHost:@"www.stackoverflow.com"]; self.reachability.notificationName = kDefaultNetworkReachabilityChangedNotification; self.reachability.onReachabilityChanged = ^(KSReachability *reachability) { NSLog(@"isReachable: %i", reachability.reachable); }; 

Je reçois toujours isReachable: 1 là avec la configuration suivante:

  • connecté à Wifi
  • configuré mon iMac en tant que proxy HTTP
  • bloquer www.stackoverflow.com dans mon Charles Proxy

Lorsque j'essaie d'atteindre www.stackoverflow.com dans Safari, la page ne peut pas être ouverte (comme prévu). Je m'attendrais à ce que l'atteignabilité soit fausse ( isReachable: 0 ) dans ce cas.

EDIT Alors la question la plus importante pour moi est – comment atteindre le comportement que j'attends? C'est à dire que l'application vérifie en permanence si l'hôte donné est vraiment accessible?

L'instruction de code:

 self.reachability = [KSReachability reachabilityToHost:@"www.stackoverflow.com"]; 

appelle en fait la méthode ci-dessous:

 SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8Ssortingng]); 

La reference SCNetworkReachability indique:

L'interface de programmation SCNetworkReachability permet à une application de déterminer l'état de la configuration réseau actuelle d'un système et l'accessibilité d'un hôte cible. Un hôte distant est considéré comme accessible lorsqu'un package de données, envoyé par une application dans la stack réseau, peut quitter le périphérique local. L'accessibilité ne garantit pas que le package de données sera effectivement reçu par l'hôte.

L'explication efface que le système iOS n'envoie aucune request au monde extérieur pour vérifier l'accessibilité. Il indique simplement que le package de données peut quitter l'appareil ou non. Si le système devait envoyer la request, cela signifie automatiquement qu'il est connecté au réseau.

Vous pouvez le vérifier en mentionnant un hôte valide comme "www.stackoverflow.com" et vérifier dans charles (d'abord débloquer) qu'aucune request n'est envoyée. Vous pouvez également vérifier avec d'autres noms d'hôtes valides comme "www.abcdefgh.com" ( vérifier cela en l'exécutant dans Safari et voir dans charles) il vous donne également l'accessibilité mais charles montre aucune request. Aussi si vous mettez http: // avant tout hôte valide, quelque chose comme " http://www.stackoverflow.com " il échouera également à l'accessibilité. Il est donc clair que ce n'est pas une requête HTTP sortante. Si le système doit envoyer une request à l'extérieur, à quoi sert la class? Un développeur peut avoir créé une connection réseau et essayer de se connecter à un hôte pour voir s'il échoue ou s'il échoue.

Cependant, il est intéressant que si un hôte invalide comme "www.hjjkhkhk.com" est fourni système iOS donne l'accessibilité fausse. Maintenant, la question est de savoir comment le système iOS trouve un hôte valide ou invalide sans envoyer de requête au monde extérieur? Peut être qu'il met périodiquement en cache une list de plages DNS? Très improbable pour moi.

Dans votre AppDelegate ajoutez cette méthode:

 #import "Reachability.h" -(NSSsortingng *)checkNetworkConnectivity { NSSsortingng *networkValue; Reachability *rc = [Reachability reachabilityWithHostName:@"www.stackoverflow.com"]; NetworkStatus internetStatus = [rc currentReachabilityStatus]; if(internetStatus==0) { networkValue = @"NoAccess"; } else if(internetStatus==1) { networkValue = @"ReachableViaWiFi"; } else if(internetStatus==2) { networkValue = @"ReachableViaWWAN"; } else { networkValue = @"Reachable"; } return networkValue; } 

Vérifier si l'hôte est joignable

 NSSsortingng *netStr = [appDelegate checkNetworkConnectivity]; if([netStr isEqualToSsortingng:@"NoAccess"]) { [appDelegate callNoNetworkAlert]; } 

Premièrement, à less de voir du code, nous ne pouvons pas nous assurer de ce que vous faites, vous faites le bon path. Cependant, je suppose que vous le faites correctement.

Deuxièmement, vous devriez tester ce que FreeNickname a suggéré dans son commentaire. Peut-être que ce n'est pas réellement inaccessible, et l'accessibilité agit correctement, quand vous attendez une réponse différente.

Dernier, mais très important, des docs d'accessibilité :

Remarque: L'accessibilité ne peut indiquer à votre application si vous pouvez vous connecter à un hôte particulier, mais seulement qu'une interface est disponible pouvant autoriser une connection et si cette interface est le réseau WWAN.

Ce que cela signifie est que, même si votre server ne renvoie aucune réponse, Reachability ne vérifie pas cela. Il vérifie seulement si votre server est disponible, de sorte qu'un package puisse être envoyé . Ce qu'il fait avec ce package ne concerne pas l'accessibilité. Si Reachability est capable de transmettre le package entier, il suppose que votre hôte est joignable. Il returnnera inaccessible si votre server est en panne, déconnecté ou n'existe pas.

Je voudrais append que pour écouter les changements de réseau au moment de l'exécution, vous devez écouter les notifications qui vous indiquent qu'un état de réseau a été changé.

Voici comment vous pouvez faire ceci:

  1. Implémentez un écouteur dans le file AppDelegate .

[[NSNotificationCenter defaultCenter] addObserver: auto-sélecteur: @selector (reachabilityChanged 🙂 nom: object kReachabilityChangedNotification: nil];

  • Maintenant, reachabilityChanged sera appelé quand il y a un changement dans l'état du réseau (peut-être la connectivité de la connection Internet ou sa déconnection). Vous pouvez effectuer une gestion appropriée dans l'événement reachabilityChanged

comme:

 - (void) reachabilityChanged:(NSNotification *)note { Reachability* reachability = [note object]; if (reachability == self.hostReachability) { isHostReachable = YES; //A flag to keep track of connectivity } if (reachability == self.internetReachability) { isInternetAvailable = YES; } if (reachability == self.wifiReachability) { isWifiAvailable = YES; } //If all are true that means we have host and Internet available if (isHostReachable && isInternetAvailable && isWifiAvailable) { isInternetAvailable = true; } } 

J'espère que ceci vous aidera.

AFNetworking

Un framework réseau iOS et OS X très agréable http://afnetworking.com


Gestionnaire d'accessibilité réseau

AFNetworkReachabilityManager surveille l'accessibilité des domaines et des adresses pour les interfaces réseau WWAN et WiFi.

Accessibilité au réseau partagé

 [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { NSLog(@"Reachability: %@", AFSsortingngFromNetworkReachabilityStatus(status)); }]; 

Accessibilité du gestionnaire HTTP

 NSURL *baseURL = [NSURL URLWithSsortingng:@"http://example.com/"]; AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL]; NSOperationQueue *operationQueue = manager.operationQueue; [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: [operationQueue setSuspended:NO]; break; case AFNetworkReachabilityStatusNotReachable: default: [operationQueue setSuspended:YES]; break; } }];