【问题标题】:Check if Internet access is available检查是否可以访问 Internet
【发布时间】:2020-04-26 05:06:12
【问题描述】:

在我的应用中,我只想在可以访问互联网的情况下进行网络呼叫。

注意:我连接到没有互联网的 WiFi 点

我想测试互联网是否可用。我尝试使用如here 所述的可达性,并且我还尝试了如here 所述的更简单的解决方案

问题在于,Reachability 是它返回 Internet 是可访问的,而实际上它不是。另一种解决方案需要太多时间才能给出响应。我尝试为请求和会话设置超时间隔,但它被忽略了。

如果我连接到没有互联网的 wifi,如何测试互联网可访问性?

这是我使用的一些代码:

- (void) postAsyncTaskWithUrl:(NSString*)urlString
                      andType:(NSString*)requestType
                     andToken:(NSString*)token
          andPropertiesObject:(id)propObject
                   urlEncoded:(BOOL)isUrlEncoded
                  withSuccess:(nullable void(^)(id _Nullable))success
                   andFailure:(nullable void(^)(id _Nullable))failure
{

    internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com"];

    __weak typeof(self) weakSelf = self;
    // Internet is reachable
    internetReachableFoo.reachableBlock = ^(Reachability*reach)
    {
                 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlSt];
        [request setTimeoutInterval:20]; //Ignored ... WHY?

        NSURLSessionConfiguration *sessionConfigurations = [NSURLSessionConfiguration defaultSessionConfiguration];
        [sessionConfigurations setTimeoutIntervalForRequest:20]; //Ignored ... WHY?
        [sessionConfigurations setTimeoutIntervalForResource:20]; //Ignored ... WHY?
//        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfigurations];
        [[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {


     }

}

}

【问题讨论】:

标签: ios nsurlsession nsurlrequest reachability nsurlsessionconfiguration


【解决方案1】:

尽管这在过去是历史上做过的事情,但我认为不值得尝试检查网络是否可达,因为这不是可靠的事情,也不是在发出请求之前应该做的事情现在几乎在所有情况下。

根据Apple's official documentation

始终尝试建立连接。不要试图猜测是否 网络服务可用,并且不缓存该确定

类似blog post from Jared Sinclair on this topic,使用SCNetworkReachability(这是可达性库在后台使用的):

SCNetworkReachability 应该只用于影响您对已经失败的网络请求执行的操作,而不应用于影响尚未尝试的初始请求。使用否定状态来确定您是否尝试自动重试,或者调整警报的面向用户的语言。使用肯定状态来考虑重试之前失败的请求。永远不要仅仅因为 SCNetworkReachability 认为没有可达网络而阻止用户发起的请求被尝试

借用a recent Reddit thread:

可达性是 iOS 世界中的一个或“这些主题”。这是什么意思 互联网是可达的?即使您检查网络接口, 您可能无法访问 apple.com 或 google.com。即使你 访问 Google,您可能无法访问您的本地服务器或 云。如果您检查是否可以访问您感兴趣的服务器,为什么 不立即发送请求?

【讨论】:

  • 感谢您的回复,实际上我可以在不知道是否有互联网的情况下尝试发送请求,所以我尝试将超时设置为 10 秒,我认为这应该足够了。然而,该应用程序完全忽略了这一点,我被困了超过一分钟等待回复。什么会导致超时被忽略?
  • 我不确定。这可能是由于超时仅在 10 秒内绝对没有数据传输时才会终止请求,如果它在 10 秒内开始然后继续需要 60 秒则不会终止请求(stackoverflow.com/a/35428764/447697
【解决方案2】:

TL;DR:You probably want an NSTimer.

在我的应用中,我只想在可以访问互联网的情况下进行网络呼叫。

这不是一个有意义的陈述。没有可以执行的测试可靠地意味着您可以“访问互联网”(尽管存在 NSURLErrorNotConnectedToInternet,这实际上并不意味着它所说的)。例如,您的代码试图将“www.google.com”视为“互联网”。但是完全有可能拥有一个允许数据包到达 www.google.com 的网络,但不允许访问其他任何地方。或者允许 ICMP 数据包,但不允许 HTTP 数据包。或者允许 HTTP 数据包,但不允许在某些端口上。这样的网络配置不仅是可能的,而且很常见,而且在各种方面它们看起来都像是“不在互联网上”。

您唯一能回答的是“我可以将数据包发送到特定主机并接收数据包作为回报吗?”甚至不可能知道你是否可以只发送一个数据包。如果您没有得到回报,您就不知道您的包裹是否已送达。

Reachability 回答了“如果我尝试发送数据包,我的本地网络堆栈会尝试发送数据包吗?”这个问题。这基本上是路由表中是否有可用的第一跳的问题。这并不意味着您可以实际连接;它只能告诉你绝对不会。

您使用的超时基于会话的空闲时间。但是您永远不会启动会话,因此它永远不会空闲。您要查找的超时是 TCP 超时,我预计为 4 分钟。 NSURLSession 无法配置。

如果您想要挂钟“开始到完成”超时,那么您需要run it yourself with a Timer

【讨论】:

  • 你说我从不开始会话,但不是调用[[session dataTaskWithRequest:request completionHandler:handler] resume] 意味着我开始了吗?
  • 不,我的意思是TCP会话永远不会连接,所以在URLSession层,空闲计时器没有启动。
  • 我尝试实现NSTimer机制,但它也不起作用,当我在没有互联网的情况下连接到WiFi时,一旦我执行dataTaskWithRequest,整个应用程序就会冻结大约两分钟.只有当它返回时,计时器的选择器才会触发。我不明白什么可能导致冻结,因为据我了解dataTaskWithRequest 在自己的线程上运行。
【解决方案3】:

如果您尝试加载http://captive.apple.com,它将返回硬编码字符串“Success”作为正文,如果互联网正常工作或将重定向/失败。您可以检查响应开始为 200 并且正文为“成功”。这就是 Apple 在连接到 WiFi 等机场时自动显示凭据窗口的方法 这么说 a) 没有万无一失的解决方案 b)您将浪费用户的数据(在您的用例中可能没问题?)

【讨论】:

    猜你喜欢
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 2014-09-28
    相关资源
    最近更新 更多