IOS: reachability withHostname YES, although it should be NO

I tested various structures, for example

and I would like to know if the host is available. On my iPhone, I installed iMac as a proxy (Charles) and blocked or not blocked connections, but there is always reachability. Only if I set up a non-existent host does it return NO. But if the host exists, but I block its connection, I always get isReachable . There is no way to check if the host is really accessible?

If I try with KSReachability, I do the following:

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

I always get isReachable: 1 there with the following configuration:

  • connected to wifi
  • configured my iMac as an HTTP proxy
  • blocking www.stackoverflow.com in my Charles proxy

When I try to get to www.stackoverflow.com in Safari, the page cannot be opened (as expected). I would expect reachability to be false ( isReachable: 0 ) in this case.

EDIT Therefore, the most important question for me is how to achieve the behavior that I expect? That is, that the application constantly checks whether this host is really accessible?

+6
source share
5 answers

Code Operator:

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

actually calls the method below:

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

The link to SCNetworkReachability says:

The SCNetworkReachability programming interface allows you to use the application to determine the status of the current network configuration of the system and the reachability of the target host. A remote host is considered achievable when a data packet sent by an application to the network stack can leave the local device. Accessibility does not guarantee that the data packet will actually be accepted by the host.

The explanation explains that the iOS system does not send a request to the outside world to check availability. He just says that the data packet can leave the device or not. If the system was to send a request, it automatically means that it is connected to the network.

You can verify this by specifying a valid host, for example "www.stackoverflow.com", and check the charl (unlock it first) so that no request is sent. You can also check with other valid host names, for example "www.abcdefgh". com "(check this by running it in Safari and look at charles), it also gives you accessibility, but charles does not show the request. Also, if you put http: // in front of any valid host, something like" http: / /www.stackoverflow.com "this will also make it impossible to achieve. Therefore, it is clear that this is not an outgoing HTTP request. If the system should send the request outside, then what is the point of providing a class? The developer could create a network connection and try to connect to the host and see if it passes or fails.

However, it is interesting that if an invalid host is specified, such as "www.hjjkhkhkk", the iOS system gives access as false. Now the question is, how does the iOS system find a valid or invalid host without sending any requests to the outside world? Maybe this is periodically caching a list of DNS ranges? Very unlikely for me.

+7
source

In your AppDelegate add this method:

 #import "Reachability.h" -(NSString *)checkNetworkConnectivity { NSString *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; } 

Check host availability

 NSString *netStr = [appDelegate checkNetworkConnectivity]; if([netStr isEqualToString:@"NoAccess"]) { [appDelegate callNoNetworkAlert]; } 
+4
source

Firstly, if we don’t see some code, we won’t be able to make sure what you are doing, you are doing the right way. However, I assume that you are doing it right.

Secondly, you should check what FreeNickname suggested in his comment. Perhaps this is not actually inaccessible, and reachability acts correctly when you expect another answer.

Finally, but very important, from Documents to Achieve :

Note. Accessibility cannot indicate to your application if you can connect to a specific host, only the available interface that can allow the connection, and whether this interface is WWAN.

This means that even though your server may not return any responses, Reachability does NOT check this. It only checks if your server is accessible so that the packet is sent . What he does with this package has nothing to do with reachability. If Reachability is capable of transmitting the entire packet, it assumes your host is available. It will return an unreachable iff , your server is disconnected, disconnected or does not exist.

+3
source

I would like to add that to listen to network changes in Runtime, you need to listen to notifications that tell you that the network status has been changed.

Here's how you can do it:

  • Implement a listener in the AppDelegate file.

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (reachabilityChanged :) name: kReachabilityChangedNotification object: nil];

  • Now reachabilityChanged is called when a change in the state of the network occurs (possibly connecting to an Internet connection or disconnecting it). You can do the appropriate processing in the reachabilityChanged event

as:

 - (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; } } 

Hope this helps you.

+2
source

AFNetworking

Amazing iOS and OS X infrastructure http://afnetworking.com


Network availability manager

AFNetworkReachabilityManager monitors domain availability and addresses for WWAN and WiFi network interfaces.

Shared Network Availability

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

HTTP Manager Availability

 NSURL *baseURL = [NSURL URLWithString:@"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; } }]; 
+1
source

Source: https://habr.com/ru/post/970940/


All Articles