NSURLConnection在设备重启之前随机失败

9
我一直在解决一个问题,即NSURLConnection调用会立即失败。需要完全重新启动设备或切换飞行模式才能解决此问题。仅重新启动应用程序(向上滑动)无法帮助解决问题。
一些事实:
- 所有URL均为HTTPS,与TLS 1.2兼容,并具有前向保密性。在ATS和iOS 9方面没有任何问题。该错误自iOS 7以来一直存在,并且仍然存在于9.2中。 - 应用程序不使用第三方框架。我仅使用本机的NSURLConnection调用,它们总是有效的,除非出现这种奇怪的情况。 - 没有基础设施/网络问题-同一网络上的其他设备(例如相同的WiFi)同时在同一应用程序中工作。从3G / Wifi转换无任何区别。 - 我总是实现willCacheResponse以返回nil。 - 服务托管在AWS Elastic Beanstalk上,因此有人建议可能是DNS缓存问题,如果IP地址更改,则这似乎不太可能,并且应在不同设备上同时触发多个错误,但我从未见过。 - 调用的方法是didFailWithError,瞬间,就像设备根本没有互联网连接-但是所有其他应用程序都可以工作。 - 托管应用程序使用的API的网站可以随时浏览,没有任何问题。实际上,该网站使用相同的请求获取数据。 - 返回的错误代码为-1003,kCFURLErrorCannotFindHost。我一直在关注Git上处理相同问题的线程,但无济于事。 https://github.com/AFNetworking/AFNetworking/issues/967 - 我尝试将NSURLRequestReloadIgnoringCacheData用于所有请求,但这并没有帮助。
有了这些信息,是否有人愿意猜测我可能做错了什么?我添加了赏金,因为我不知道如何解决这个问题-特别是因为它非常不一致。而且这绝对不是一个合法的错误(也就是说,域名找不到),因为服务在这种情况下的随机客户端上运行良好。
我使用一个静态方法创建我的请求,看起来像这样。它已剥离了一些非公共信息,但基本上只需使用JSON数据执行POST请求。 [Controller getSQLHost] 只返回URL-基域。
+(NSURLConnection*)initiatePOSTwithJSONDictionary:(NSDictionary*)dictionary toURL:(NSString*)urllocation withDelegate:delegate {

    NSMutableDictionary *connectionDictionary = [[NSMutableDictionary alloc] init];

    if (dictionary) {
        [connectionDictionary setObject:dictionary forKey:@"input"];
    }

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:connectionDictionary options:kNilOptions error:nil];

    NSURL *url = [NSURL URLWithString:[[Controller getSQLHost] stringByAppendingString:urllocation]];

    NSString *postLength = [NSString stringWithFormat:@"%i", (int)[jsonData length]];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
    [request setHTTPMethod:@"POST"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:jsonData];

    return [[NSURLConnection alloc] initWithRequest:request delegate:delegate];

}

你能给我网址吗? - Kirit Modi
我不能。它需要身份验证,而我无法提供。服务器没有问题。 - nickdnk
好的,谢谢。您可以使用NSURLSession调用服务。 - Kirit Modi
再次强调,这与我的问题无关。我根本不使用会话。请再次阅读问题或指出您不清楚的部分。 - nickdnk
1
@damirstuhec 在将所有网络调用替换为URLSessions后,问题得到了解决。我之后再也没有遇到过这个问题。NSURLConnection已经被弃用了。如果可能的话,你应该编写Swift代码:https://developer.apple.com/documentation/foundation/nsurlconnection - nickdnk
显示剩余21条评论
2个回答

0

你的委托实现了connectionShouldUseCredentialStorage吗?(或者回答YES)

我认为当这个方法返回yes时,设备的钥匙串被使用,这可能解释了持续失败超出运行应用程序的生命周期以及为什么重新启动或重置网络连接“修复”它。如果认证失败已经被识别一次,它可能会在钥匙串中停留一段时间,然后立即响应而不实际去服务器。

导致身份验证在钥匙串中注册为失败的原因可能取决于各种因素。它可能只是保存密码中的拼写错误,也可能更加复杂,例如某些证书过期阻止SSL层建立安全链接。


我没有实现这个方法。我使用SSKeyChain从钥匙串中检索设备令牌,每次应用程序启动时都会执行此操作。然后将其作为请求的一部分。 - nickdnk
我对这个方法的理解是,如果你不实现它,调用者会假设它返回YES,并将其存储到keyChain中。如果你正在进行自己的密钥链操作,这可能会干扰,你可能希望实现该方法使其返回NO。 - Alain T.
但这样不会导致每个调用都失败吗?我可以试一下。 - nickdnk

0

你正在当前runloop上创建NSURLConnection,同时活动的连接数有多少?你是否考虑过使用NSOperationQueue来避免负载问题?

你的代理对象线程安全吗?如果不是,那可能会解释bug的间歇性。

你说你并不经常看到这个问题,但其他人却有。你能否借用他们的设备,甚至是他们的使用模式,从而更频繁地看到这个问题?


大多数时候只有一个调用。我不会为每个用户操作创建多个请求。我不能借用他们的设备。-问题并不经常发生-此外,我不知道该怎么做,因为我能得到的唯一日志是错误1003,它告诉我什么都没有。我正在考虑转移到NSURLSession,但根据GitHub线程,这并没有什么区别。 - nickdnk
不清楚线程安全。我只是按照所有通常的 NSURLConnection 指南进行操作。其中没有提到线程安全。 - nickdnk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接