【问题标题】:How to check for network reachability on iOS in a non-blocking manner?如何以非阻塞方式检查 iOS 上的网络可达性?
【发布时间】:2012-11-26 18:32:58
【问题描述】:

在我的 iOS 项目中,我想在某些网络操作之前​​向用户显示一条连接到互联网的消息,所以我使用 Apple 的 Reachability 类编写了以下检查:

Reachability *reach = [Reachability reachabilityWithHostName:@"google.com"];
if([reach currentReachabilityStatus] == NotReachable) {
    // ...prompt user to establish an internet connection
} else {
    // ...send an asynchronous request with a timeout
}

然而,这有一个非常大的问题——当设备在一个非常有损的网络上时(例如,当 OS X Lion 的 Network Link Conditioner 上的上行链路丢包率设置为 100% 时),[Reachability reachabilityWithHostName:@"google.com"] 会阻止在确定连接不可用之前,主线程 30 秒。但是,以下代码不会阻塞:

if([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable) {
    // ...prompt user to establish an internet connection
} else {
    // ...send an asynchronous request with a timeout
}

查看 Reachability 的实现表明,这两种方法都使用SystemConfiguration.framework,但第一种方法使用SCNetworkReachabilityCreateWithName,而第二种方法使用SCNetworkReachabilityCreateWithAddress。为什么第一种方法会阻塞,而第二种方法不会呢?第二种方法是检查连通性的好方法吗?还是有更好的办法?

【问题讨论】:

    标签: objective-c ios reachability


    【解决方案1】:

    检查此功能:

    - (BOOL)isNetworkAvailable
    {
    CFNetDiagnosticRef diag;        
    diag = CFNetDiagnosticCreateWithURL (NULL, (__bridge CFURLRef)[NSURL URLWithString:@"www.apple.com"]);
    
    
    
    CFNetDiagnosticStatus status;
    status = CFNetDiagnosticCopyNetworkStatusPassively (diag, NULL);        
    
    CFRelease (diag);
    
    if ( status == kCFNetDiagnosticConnectionUp )
    {
        //NSLog (@"Connection is up");
        return YES;
    } else {
        NSLog (@"Connection is down");
        return NO;
    
    }
    }
    

    这会很好用..

    【讨论】:

    • 但是如果你想检查一个数据包是否可以交付,这也不起作用
    【解决方案2】:

    第一个测试它是否可以到达google.com,而第二个只是检查是否有任何可能的互联网连接(它认为存在,即使有数据包丢失)。

    基本上只是把它放在一个线程或后台队列中。可靠地知道您是否有良好连接的唯一方法是对其进行测试,并且任何测试都将是阻塞或异步的。您根本无法立即使用它。

    【讨论】:

    • 能否请您解释一下如何明确说明第二种方法仅检查是否可以连接?这在文档中的某处有说明吗?如果你能给我一个来源,我会把它标记为正确答案。
    • 任何 I/O 活动要么必须是阻塞的,要么是异步的,才能告诉您它是否可以做某事。在您的示例代码中,您表明它是同步的并立即返回。合乎逻辑的结论是不涉及 I/O。
    • 可能不是SCNetworkReachabilityCreateWithNameSCNetworkReachabilityCreateWithAddress之间的区别,而是reachabilityForInternetConnection检查套接字地址为零,从而跳过了检查时间密集的任务远程主机?我只是想要一个合乎逻辑的解释,在这里。
    • 说实话,我是一个比较实际的人。第一个检查它是否真的有效,第二个根据一些本地缓存的信息进行猜测。你需要知道的不就是这些吗?
    • 对我来说已经足够了,我猜。我的意思是,无论如何,您总是可以将失败块附加到请求本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2021-06-21
    • 2019-09-27
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多