如何为iOS中的网络连接测试计算有效负载大小和超时长度? [英] How to calculate payload size and timeout length for network connectivity test in iOS?

查看:126
本文介绍了如何为iOS中的网络连接测试计算有效负载大小和超时长度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序提供了从我们的服务器下载3430高分辨率图像的选项,每个图像大小为50k-600k字节.

My app offers the option to download 3430 high resolution images from our server, each image of size 50k - 600k bytes.

最初的方法是只下载所有这些文件-但是我们意识到这给了很多NSURLErrorTimedOut错误,导致程序崩溃.现在,我们已经实现了它,以便我们下载所有图像,但一次下载100张图像.

The original approach was to just download all of them - but we realized that gave a lot of NSURLErrorTimedOut errors and crashed our program. We've now implemented it such that we download all of the images, but in batches of 100 images at a time.

- (void)batchDownloadImagesFromServer:(BOOL)downloadHiResImages
{

    [UIApplication sharedApplication].idleTimerDisabled = YES;
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

    [self generateImageURLList:YES];

    [leafletImageLoaderQueue removeAllObjects];
    numberOfThumbnailLeft = [uncachedThumbnailArray count];
    numberOfHiResImageLeft = [uncachedHiResImageArray count];

    NSLog(@"DEBUG: In batchDownloadImagesFromServer numberOfThumbnailLeft %ul , numberOfHiResImageLeft %ul ", numberOfThumbnailLeft, numberOfHiResImageLeft);

    numberOfImagesToDownload = numberOfThumbnailLeft;
    if (downloadHiResImages)
    {
        numberOfImagesToDownload += numberOfHiResImageLeft;
    }

    if (numberTotalToDownload < 0) {
        numberTotalToDownload = numberOfHiResImageLeft;
    }

    int midBatchCt = 0;
    // start where we stopped
    NSArray *subArray;
    NSRange batchRange;
    batchRange.location = 0;//uncachedHiResIndex;
    NSInteger uncachedNumber = [uncachedHiResImageArray count];
    NSLog(@"uncachedHiResIndex and numberTotalToDownload: %d %d", uncachedHiResIndex, numberTotalToDownload);
    if (uncachedHiResIndex >= numberTotalToDownload || batchRange.location >= uncachedNumber) {
        // we have reached the end of the uncached hires images

        NSLog(@" END of download total to download=%ld , uncachedNumber=%ld, # not downloaded is %ld", (long)numberTotalToDownload, uncachedNumber, (long)numberFailedToDownload);
        return;
    }
    if (batchRange.location+100 > uncachedNumber) {
        NSInteger imagesUntilEnd = uncachedNumber -1;
        batchRange.length = imagesUntilEnd;
        NSLog(@"this is uncached number: %d this is uncachedhiresindex:%d and this images until end:%d ", uncachedNumber, uncachedHiResIndex, imagesUntilEnd);

    } else {
        batchRange.length = 100;
    }
    NSLog(@" NEW RANGE is from %lul to %lul ", (unsigned long)batchRange.location, batchRange.length);
    subArray = [uncachedHiResImageArray subarrayWithRange:batchRange];
    if (downloadHiResImages)
    {
        for ( LeafletURL* aLeafletURL in subArray )
        {
            LeafletImageLoader* hiResImageLoader = [[LeafletImageLoader alloc] initWithDelegate:self];
            [leafletImageLoaderQueue addObject:hiResImageLoader]; // do this before making connection!! //

            [hiResImageLoader loadImage:aLeafletURL isThumbnail:NO   isBatchDownload:YES];

            //// Adding object to array already retains it, so it's safe to release it here. ////
            [hiResImageLoader release];

            midBatchCt++;
            uncachedHiResIndex++;
            if (midBatchCt == 10) {
                NSLog(@" Waiting for queued images to download...");
                NSLog(@" REMOVED from QUEUE %lul , UncachedIndex %lul", numberRemovedFromQueue, uncachedHiResIndex);
                break;
            }
        }
    }



    if ( [leafletImageLoaderQueue count] == 0 && numberRemovedFromQueue == numberTotalToDownload) {
        if([delegate respondsToSelector:@selector(requestDidBatchDownloadImages:)])
        {
            [delegate requestDidBatchDownloadImages:self];
        }
    }


}

这已解决了我们的大多数问题.但是,即使在开始批量下载之前,我们也要测试网络连接性.我发现了一个低级ping库,该库可提供准确的往返计时结果.使用GBPing的演示代码作为参考,在调用batchDownloadImagesFromServer之前,我编写了自己的代码来ping服务器.

This has resolved most of our issues. However, we would like to test for network connectivity before even beginning batch downloading. I found a low level ping library that gives accurate round-trip timing results. Using the demo code from GBPing as a reference, I wrote my own code to ping our server before we call batchDownloadImagesFromServer.

- (IBAction)preloadAll:(id)sender
{
self.ping = [GBPing new];
    self.ping.host = kDefaultDataServer;
    self.ping.delegate = self;
    self.ping.timeout = 1;
    self.ping.pingPeriod = 0.9;

    // setup the ping object (this resolves addresses etc)
    [self.ping setupWithBlock:^(BOOL success, NSError *error) {
        if (success) {
            // start pinging
            [self.ping startPinging];

            // stop it after 5 seconds
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"stop it");
                [self.ping stop];
                self.ping = nil;
            });
        } else {
            UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Internet Connection"
                                                                            message:@"Not strong enough internet connection"
                                                                     preferredStyle:UIAlertControllerStyleAlert];

            UIAlertAction* OKButton = [UIAlertAction
                                        actionWithTitle:@"Ok"
                                        style:UIAlertActionStyleCancel
                                        handler:^(UIAlertAction * action) {
                                            [downloadManager batchDownloadImagesFromServer:YES];
                                        }];

            [alert addAction:OKButton];
            [self presentViewController:alert animated:NO completion:nil];
        }

    }];
}

我是刚接触网络的新手.考虑批处理大小和图像大小,如何确定测试的有效负载大小和超时长度?

I am completely new to networking. How do I determine the payload size and timeout length for my test considering the batch size and the size of the images?

推荐答案

超时长度是每个请求的长度.这只是网络代码在放弃之前等待答复的时候.长度不应该太短,但是对于大多数系统API来说,超时时间大约是一分钟或更长时间,这可能太长了.

Timeout length is per request. It is just the time the networking code will wait for a reply before it gives up. This shouldn't be too short, but for most system API, timeout length is something around a minute or more, which is probably too long.

此外,请注意,如果连接不良,您仍然会收到超时错误,因此需要修复导致崩溃的原因.您必须能够从超时中恢复.

Also, note that you will still get time out errors if connectivity is bad, so whatever caused your crashes needs to be fixed. You have to be able to recover from time-outs.

您没有提供太多有关崩溃的信息(这是什么崩溃?您得到什么回溯?),但是我可以看到可能发生的三件事:

You're not giving much information about your crash (what kind of crash is it? What backtrace do you get?), but I can see three obvious things that may be happening:

  1. 您以严格的循环进行了下载,其中没有@autoreleasepool {}块.这意味着您所有下载的文件数据都累积在RAM中,并耗尽了应用程序的内存限制.确保将自动释放池置于长时间运行的循环中.

  1. You did your downloading in a tight loop without an @autoreleasepool {} block inside it. This means that all your downloaded file data accumulated in RAM and blew your app's memory limit. Be sure to put autorelease pools in long-running loops.

您正在主线程上进行这些下载.主线程用于UI和简短操作.如果您的主线程代码执行的操作花费的时间超过几秒钟,则UIApplication将无法处理来自用户的触摸事件(以及其他事件),并且操作系统会将其击落为无响应.将较长的操作卸载到调度队列上(或使用其他方式将操作移出主线程,例如,使用异步API).

You were doing these downloads on the main thread. The main thread is for the UI and short actions. If your main thread code does anything that takes longer than a few seconds, UIApplication will not get to process touch events from the user (and other occurrences) and the operating system will shoot it down as being unresponsive. Offload longer operations onto a dispatch queue (or use some other way to move the actions off the main thread, e.g. by using asynchronous API).

您正在向服务器发送大量请求,并且服务器内部的某些DDoS保护功能决定在几分钟内忽略来自您的请求,这是一种自我保护的形式.许多服务器在给定的时间内限制了它们将接受来自客户端的请求数量,或者客户端可能同时具有多少个打开的连接.

You are flooding your server with requests, and some DDoS-protection inside it decides to just ignore requests from you for a few minutes as a form of self-protection. Many servers have limits on how many requests they will accept from a client within a given period of time, or how many open connections a client may have at the same time.

我认为,通过显示执行实际下载的代码,可以为您提供更好的服务.您不应该需要来获取准确的ping定时信息,以下载一堆图像文件.

I think you would be much better served by showing the code that performs the actual download. You should not need to get accurate ping timing information to download a bunch of image files.

假设上述可能性中的一种或多种是正确的,我建议您像这样实现您的下载代码:

Assuming one or more of the above possibilities are true, I'd suggest you implement your download code like this:

  1. 创建所有需要下载的文件URL的列表.

  1. Create a list of all file URLs that need to be downloaded.

编写代码,以便其顺序下载这些URL. IE.在上一个文件完成(或失败并且您决定暂时跳过该文件)之前,不要让它开始下载文件.

Write your code so that it downloads these URLs sequentially. I.e. do not let it start downloading a file until the previous one has finished (or failed and you decided to skip it for now).

使用NSURLSession的支持将单个文件下载到文件夹,请勿使用代码获取NSData并自己保存文件.这样,下载完成时无需运行您的应用程序.

Use NSURLSession's support for downloading an individual file to a folder, don't use the code to get an NSData and save the file yourself. That way, your application doesn't need to be running while the download finishes.

请确保您可以判断文件是否已下载,以防下载中断或在下载中重启手机.您可以例如为此,可以比较它们的名称(如果它们足够独特),或将注释保存到plist中,以使您将下载的文件与文件的来源网址进行匹配,或者构成您情况下的识别特征.

Ensure that you can tell whether a file has already been downloaded or not, in case your download gets interrupted, or the phone is restarted in mid-download. You can e.g. do this by comparing their names (if they are unique enough), or saving a note to a plist that lets you match a downloaded file to the URL where it came from, or whatever constitutes an identifying characteristic in your case.

在启动时,检查是否所有文件都在那里.如果不是,请将丢失的文件放在上面的下载列表中,然后按顺序下载它们,如#2所示.

At startup, check whether all files are there. If not, put the missing ones in above download list and download them sequentially, as in #2.

在开始下载任何内容(包括在先前的下载完成或失败之后下载下一个文件)之前,请使用Apple的SystemConfiguration.framework中的Reachability API进行可达性检查.这将告诉您用户是否完全建立了连接,以及您使用的是WiFi还是蜂窝网络(通常,您不是希望通过大多数蜂窝网络通过蜂窝网络下载大量文件被计量).

Before you start downloading anything (and that includes downloading the next file after the previous download has finished or failed), do a reachability check using the Reachability API from Apple's SystemConfiguration.framework. That will tell you whether the user has a connection at all, and whether you're on WiFi or cellular (in general, you do not want to download a large number of files via cellular, most cellular connections are metered).

如果图像存储在单独的服务器上,或者它们较小,并且设置连接的开销比实际下载数据要多,则可以修改代码以一次下载多个图像,但是通常情况下,同时从服务器下载4个以上的图像,您可能看不到性能提升,因为每增加一个图像都会减少其他图像的可用带宽.

If your images are stored on separate servers, or they are comparatively small and there is more overhead setting up the connection than actually downloading the data, you could modify the code to download several images at once, but usually if you're downloading more than 4 images from a server at the same time, you'll likely not see a performance benefit, as every additional image will just reduce the amount of bandwidth available for the others.

这篇关于如何为iOS中的网络连接测试计算有效负载大小和超时长度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆