iOS:reachabilityWithHostname YES虽然它应该是NO

时间:2014-06-17 09:57:23

标签: ios reachability

我测试了不同的框架,例如

我想知道主机是否可以访问。在我的iPhone上,我将iMac设置为代理(Charles)并阻止或不阻止连接,但可达性始终为YES。仅当我设置不存在的主机时,它才返回NO。但是如果主机存在但我阻止了与它的连接,我总是得到isReachable。是不是有办法检查主机真的是否可以访问?

如果我尝试使用KSReachability,我会执行以下操作:

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

我总是通过以下配置获得isReachable: 1

  • 已连接至Wifi
  • 将我的iMac配置为HTTP-Proxy
  • 在Charles Proxy中阻止www.stackoverflow.com

当我尝试在Safari中访问www.stackoverflow.com时,页面无法打开(正如预期的那样)。在这种情况下,我希望可达性为假(isReachable: 0)。

修改 所以对我来说最重要的问题是 - 如何实现我期待的行为?即应用程序会不断检查给定主机是否真的可以访问?

5 个答案:

答案 0 :(得分:7)

代码声明:

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

实际上调用以下方法:

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

SCNetworkReachability参考说:

  

SCNetworkReachability编程接口允许应用程序   确定系统当前网络配置的状态   以及目标主机的可达性。考虑远程主机   当数据包由应用程序发送到网络时可达   堆栈,可以离开本地设备。可达性不保证   实际上主机将接收数据包。

说明清除iOS系统不向外界发送任何请求以检查可达性。它只是告诉数据包可以离开设备。如果系统要发送请求,它会自动表示它已连接到网络。

您可以通过提及“www.stackoverflow.com”这样的有效主机来验证这一点,并查看未发送请求的查尔斯(首先取消阻止)。您还可以查看其他有效的主机名,例如“www.abcdefgh。 com“(通过在Safari中运行并查看查尔斯来验证这一点)它还为您提供了可访问性,但查尔斯没有显示请求。如果您在任何有效主机之前放置http://,例如”http://www.stackoverflow.com“它也将无法达到可达性。所以很明显它不是传出的http请求。如果系统必须在外面发送请求,那么提供课程的重点是什么?开发人员可以创建网络连接并尝试连接到主机,看看它是通过还是失败。

然而有趣的是,如果提供像“www.hjjkhkhk.com”这样的无效主机,iOS系统会将可达性视为错误。现在的问题是iOS系统如何在不向外界发送任何查询的情况下找到有效或无效的主机?可能是它定期缓存DNS范围列表???对我来说非常不可能。

答案 1 :(得分:4)

AppDelegate添加此方法:

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

检查主机是否可以访问

NSString *netStr = [appDelegate checkNetworkConnectivity];

if([netStr isEqualToString:@"NoAccess"])
{
     [appDelegate callNoNetworkAlert];
}

答案 2 :(得分:3)

首先,除非我们看到一些代码,否则我们无法确定您正在做什么,您正在以正确的方式行事。但是我会假设你正确地做到了。

其次,您应该测试FreeNickname在评论中建议的内容。可能它实际上并不可达,并且当您期望有不同的响应时,可达性正确起作用。

最后,但非常重要,来自Reachability docs

  

注意:如果您可以连接到特定主机,只有可用于允许连接的接口以及该接口是否为WWAN,则可访问性无法告诉您的应用程序。

这意味着,即使您的服务器可能没有返回任何响应,Reachability也不会检查。它仅检查您的服务器是否可用,以便可以发送数据包。它对该数据包的作用与Reachability无关。如果Reachability能够传输整个数据包,则假定您的主机可以访问。它将返回无法访问 iff 您的服务器已关闭,断开连接或不存在。

答案 3 :(得分:2)

我想补充一点,要在运行时收听网络更改,您需要收听告知您网络状态已更改的通知。

您可以这样做:

  1. AppDelegate文件中实现一个侦听器。
  2.   

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

    • 当网络状态发生变化(可能是互联网连接的连接或断开连接)时,将调用reachabilityChanged。您可以在reachabilityChanged活动
    • 中进行适当的处​​理

    像:

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

    希望这会对你有所帮助。

答案 4 :(得分:1)

AFNetworking

令人愉快的iOS和OS X网络框架 http://afnetworking.com


网络可达性管理器

AFNetworkReachabilityManager监控域的可达性,以及WWAN和WiFi网络接口的地址。

共享网络可达性

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

HTTP Manager可达性

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