checking reachability against a specific page in a URL

JAHelia picture JAHelia · Mar 8, 2012 · Viewed 8.2k times · Source

After I have read the answer for this question I have found that using reachabilityWithHostName does not work with a URL such as this one: mySite.com/service.asmx , is there anyway to check reachability against this URL using reachabilityWithHostName or any reachability class method ?

thanks so much in advance.

Answer

gaige picture gaige · Mar 8, 2012

The Reachability class and -reachabilityWithHostname: is designed to be a quick, fail-fast mechanism to determine whether you have basic network connectivity to the host. If you need to verify that a particular URL can be downloaded, you need to be looking at using NSURLConnection to retrieve the contents of the URL in order to verify that it is truly available.

Depending on whether you need to do this in the foreground or background, you can either use the simple-but-blocking:

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

or you can use the more complicated method of creating an NSURLConnection object, setting up a delegate to receive responses and wait for those responses to come in.

For the simple case:

 NSURL *myURL = [NSURL URLWithString: @"http://example.com/service.asmx"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myURL];
 [request setHTTPMethod: @"HEAD"];
 NSURLResponse *response;
 NSError *error;
 NSData *myData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];

If you receive back a non-nil myData, you've got some kind of connectivity. response and error will tell you what the server responded to you (in the case of response and if you received a non-nil myData) or what kind of error occurred, in the case of a nil myData.

For the non-trivial case, you can get good guidance from Apple's Using NSURLConnection.

If you don't want to stall your foreground process, you can do this two different ways. The above documentation will provide information on how to implement the delegate, etc. However, a simpler implementation would be to use GCD to send the Synchronous request on a background thread, and then message yourself on the main thread when you are done.

Something like this:

 NSURL *myURL = [NSURL URLWithString: @"http://example.com/service.asmx"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myURL];
 [request setHTTPMethod: @"HEAD"];
 dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, NULL), ^{
      NSURLResponse *response;
      NSError *error;
      NSData *myData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
      BOOL reachable;

      if (myData) {
            // we are probably reachable, check the response
            reachable=YES;
      } else {
            // we are probably not reachable, check the error:
            reachable=NO;
      }

      // now call ourselves back on the main thread
      dispatch_async( dispatch_get_main_queue(), ^{
            [self setReachability: reachable];
      });
 });