Is it wise to use Reachability to check for a remote host's availability?

我们两清 提交于 2019-12-18 13:38:36

问题


Is it wise to use Reachability Class(from Apple) to check for a remote host's availability ? say for example, www.google.com

or should I use

NSString *connectedString = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com/"]]; 

if ([connectedString length] != 0) // Host Available

Which is the best option since I've heard that Reachability is having bug with checking for host's availability ?


回答1:


Here is a good way to check if host is reachable:

    NSURLResponse *response=nil;
    NSError *error=nil;
    NSData *data = nil;
    NSURLRequest *request = [NSURLRequest requestWithURL:your_url];

    data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

If host is offline you will receive some error code in error, nil in data and nil in response variables.
If host is online and responds there will be some response, data, and error==nil.




回答2:


Reachability will not tell you if a remote host is contactable. It only tests the first hop i.e. can you send a packet to your router. If the router cannot reach the wider internet, reachability will still tell you that you have a wifi connection. You have to implement one of the other suggested solutions to test "true" reachability.




回答3:


As mentioned by others, reachability detects changes in your hardware instead of the real availability of a server. After reading many posts and breaking my head I came up with this code.

Here is a full implementation of a ReachabilityManager class that uses both Reachability and URLConnection to make sure that the connection is available or not. Please note that depends on the Reachability classes (I am using the Tony Million implementation but I am sure it works with the Apple one)

If you test this in the simulator and enable/disable your wireless connection you will see that it detects (sometimes takes a few seconds) the connection/disconnection. Something that before with just the reachability class did not work.

I have also added a couple of notifications that are more effective than the ones from Reachability for the rest of your code. You may want to handle this in a different way.

Also, this is a singleton so you can instantiate if from anywhere. You can convert it to a non static class and instantiate it from the AppDelegate.

I hope this is useful for anybody breaking her/his head with why reachability is not properly detecting the availability.

If you guys have time to create some UnitTests for it let me know so we can share more knowledge around the Reachability.

Just create a new NSObject class and copy this contents:

.h

#import <Foundation/Foundation.h>
@interface ReachabilityManager : NSObject

+ (void)startReachabilityWithHost : (NSURL *)hostName;

@end

.m

#import "ReachabilityManager.h"
#import "Reachability.h"

@implementation ReachabilityManager

static ReachabilityManager *_sharedReachabilityManager;
static Reachability *reachability;
static NSURL *_hostName;
static BOOL isServerReachable;
+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        _sharedReachabilityManager = [[ReachabilityManager alloc] init];
    }
}

+ (void)startReachabilityWithHost : (NSURL *)hostName{
    _hostName = hostName;

    reachability = [Reachability reachabilityWithHostname:hostName.host];

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

+ (void)stopReachability{
    [reachability stopNotifier];
    [[NSNotificationCenter defaultCenter]removeObserver:kReachabilityChangedNotification];
}

+(void)reachabilityChanged: (NSNotification *)notification{
    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        BOOL isServerCurrentlyReachable = NO;
        do{
            isServerCurrentlyReachable = [self checkConnectivityToServer];
            BOOL wasServerPreviouslyReachable = isServerReachable;
            isServerReachable = isServerCurrentlyReachable;

            if (NO == wasServerPreviouslyReachable && YES == isServerCurrentlyReachable)
            {
                NSLog(@"REACHABLE!");
                [[NSNotificationCenter defaultCenter]postNotificationName:@"kNetworkReachabilityCustom" object:[NSNumber numberWithBool:YES]];
            }
            else if (YES == wasServerPreviouslyReachable && NO == isServerCurrentlyReachable)
            {
                NSLog(@"UNREACHABLE!");
                [[NSNotificationCenter defaultCenter]postNotificationName:@"kNetworkReachabilityCustom" object:[NSNumber numberWithBool:NO]];
            }
            [NSThread sleepForTimeInterval:5.0];
        }while(!isServerCurrentlyReachable);
    });

}


+(BOOL)checkConnectivityToServer{
    NSURLResponse *response;
    NSError *error=nil;
    NSData *data = nil;
    NSURLRequest *request = [NSURLRequest requestWithURL:_hostName];

    data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    return (data && response);

}


@end



回答4:


It is wise to check if you have any internet connection first, and for that I use Reachability. And I try to do my connection with the server only I have internet.




回答5:


Here is a tutorial on how to use Reachability. http://www.raddonline.com/blogs/geek-journal/iphone-sdk-testing-network-reachability/

NSString *connectedString = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com/"]]; 

if ([connectedString length] != 0) // Host Available

The code you provided should also work but might not give the desired result.. Reachability is more reliable..




回答6:


The following code from developer.apple.com might help you..

// Create the request.

NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]

                        cachePolicy:NSURLRequestUseProtocolCachePolicy

                    timeoutInterval:60.0];

// create the connection with the request

// and start loading the data

NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

if (theConnection) {

    // Create the NSMutableData to hold the received data.

    // receivedData is an instance variable declared elsewhere.

    receivedData = [[NSMutableData data] retain];

} else {

    // Inform the user that the connection failed.

}


来源:https://stackoverflow.com/questions/4756376/is-it-wise-to-use-reachability-to-check-for-a-remote-hosts-availability

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!