NSURLConnection在约5分钟后忽略服务器响应 - 没有超时

时间:2015-12-16 22:23:49

标签: objective-c cocoa http timeout nsurlconnection

我遇到NSURLConnection的问题,我现在暂时无法解决这个问题。

我向服务器发出请求,但数据需要很长时间才能处理(平均约7分钟)。因此客户端需要等待响应,因此我尝试通过在NSURLRequest中设置很长时间来保持HTTP连接打开。我不希望在此时使用基于投票的解决方案。

请求代码:

- (void)sendNextExample
{
    url = ...
    json = ...

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                           cachePolicy:NSURLRequestReloadIgnoringCacheData
                                                       timeoutInterval:600.0];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:json];
    NSURLConnection *newConnection = [[NSURLConnection alloc] initWithRequest:request
                                                                     delegate:self
                                                             startImmediately:NO];
    if (!queue)
    {
        queue = [NSOperationQueue new];
    }
    [newConnection setDelegateQueue:queue];

    self.connectionStatus = @{@"index" : @(i), @"data" : [NSMutableData data]};
    [newConnection start];
}

处理代码(简化):

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSMutableData *buffer = self.connectionStatus[@"data"];
    [buffer appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // log and interrupt process
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do sth with buffer data
    // finalize
}

问题是,我从未收到任何来自服务器和连接超时(600秒= 10分钟后,如NSURLRequest中所定义),,即使该过程似乎已完成在服务器端。在连接超时之前,任何委托方法都不会被调用。

为了验证服务器进程并将数据正确地返回给客户端,我通过使用curl执行从完全相同的客户端到完全相同的服务器的多个请求进行测试:

curl -H "Content-Type: application/json" -X POST -d '{"foo":0.0, "bar":1.0}' serveraddress:8000

这些请求似乎按预期工作,即上述内容在7分钟后返回正确的数据:

{"bar":0.5, "baz":10.0} // expected data

我怀疑,因为罪魁祸首在于NSURLConnection,所有其他事情都是一样的。

作为下一步,我已经使用不同持续时间的服务器端进程执行了多个请求,并发现NSURLConnection在请求后大约5分钟后开始忽略响应。

所以问题是,当然,有没有人经历过这个?这种行为是否正常/预期?

是否有任何理由(甚至是OS介导的)NSURLConnection会忽略在一定时间后收到的数据,即使在请求中正确设置了超时?任何细则或无证的特征"可能导致这种情况?

最终,切换到NSURLConnection以外的其他内容,例如AFNetworking,让我有机会绕过这个明显的限制"?

(当然,如果对如何以另一种方式执行任务有任何建议,他们也会非常欢迎!)

为了清楚起见,客户端是Yosemite机器(Xcode 7),服务器是使用.Net 4.5(Windows 8机器)中的HttpListener编写的。该服务器已在其他场合进行过测试,并按预期工作。

编辑:此问题发布后半年多,问题仍然存在。我设法通过从可可调用curl来做我的工作(不优雅,但工作),因此无数次验证了罪魁祸首确实在NSURLConnection。我终于得出结论,这是一个错误,并将发布它(如果我有时间这样做),但说实话,我不会过多地抱怨我。

EDIT2 :轮询显然是另类选择。但是,我不能使用轮询,因为我的一些请求需要返回非常快(<< 1sec),而其他请求需要很长时间(> 1分钟)。使用轮询意味着增加请求/响应所需的最短时间。

1 个答案:

答案 0 :(得分:0)

如果NSURLConnection失败,NSURLSession和基于它的所有内容都有可能发生,所以不,AFNetworking不应该有任何区别。

我很好奇你为什么要为每个请求创建一个单独的NSOperationQueue实例。这非常浪费资源; NSURLConnection本质上是异步的,因此它不会阻止操作队列,除非它正在运行回调代码。除非您的委托方法由于某种原因必须进行一些严重的繁重工作,否则很少有理由使用您自己的操作队列。

无论哪种方式,即使使用curl(你应该只是链接到libcurl,如果你真的需要这样做而不是运行一个单独的进程),那么这个设计仍然存在根本问题,因为一旦你最终陷入困境网络,您在服务器完成处理请求之前很久就会超时。此外,如果连接似乎不再使用,则某些基于NAT的防火墙可能会忘记映射,此时您的请求将永远无法完成。

将方法更改为上传数据的方法要好得多,服务器会为您提供一个URL,您可以在其中检查进度,并且客户端请求该URL,然后服务器提供状态。然后,您的客户端可以经常重新检查状态,最终通过发出检索已处理数据的请求并删除服务器上的文件来结束。

如果您不介意在网络服务器中保留一个帖子,您也可以使用MIME多部分响应,这样当您询问该状态URL的内容时,Web服务器会发回一个新状态blob每个 n 秒,但这是否是一个好主意取决于您的服务器架构。