5

Im making an app where one of the features I want to offers is to measure de download speed of the connection. To get this I`m using NSURLConnection to start the download of a large file, and after some time cancel the download and make the calculation (Data downloaded / time elapsed). While other apps like speedtest.net give a constant speed every time, mine fluctuates 2-3 Mbps more or less.

Basically what I`m doing is, start the timer when the method connection:didReceiveResponse: is called. After 500 call of the method connection:didReceiveData: I cancel the download, stop the timer and calculate the speed.

Here is the code:

- (IBAction)startSpeedTest:(id)sender 
{
    limit = 0;
    NSURLRequest *testRequest = [NSURLRequest requestWithURL:self.selectedServer  cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];

    NSURLConnection *testConnection = [NSURLConnection connectionWithRequest:testRequest delegate:self];
    if(testConnection) {
        self.downloadData = [[NSMutableData alloc] init];
    } else {
        NSLog(@"Failled to connect");
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    self.startTime = [NSDate date];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.downloadData appendData:data];
    if (limit++ == 500) {
        [self.connection cancel];
        NSDate *stop = [NSDate date];
        [self calculateSpeedWithTime:[stop timeIntervalSinceDate:self.startTime]];
        self.connection = nil;
        self.downloadData = nil;
    }
}

I would like to know if there is a better way of doing this. A better algorithm, or a better class to use.

Thanks.

pedros
  • 1,197
  • 10
  • 18
  • Are you using your own server? – Jack Humphries Sep 04 '12 at 21:33
  • Im using a university server in my city. – pedros Sep 04 '12 at 21:40
  • 1
    Speed Test has many servers that have insanely fast Internet connections (required to be 100 Mb/s +). So if someone is in a different country and using your app, their distance is going to cause the data to take longer to transfer, and therefore the app will report an inaccurate speed. Also, if a bunch of people are doing it at once (not sure of you server's speed), the server could slow down also causing the data to take longer to transfer. I would recommend finding a file on Google and download that. Google has quite a few data centers in different locations. – Jack Humphries Sep 04 '12 at 21:49
  • The google file is a good idea. The app is targeted only for my country (Brazil), so I was thinking in using the university servers from all over the country. But still, I cant figure out a more precise way to measure the speed. I don`t know how the speedtest.net mobile app does it. – pedros Sep 04 '12 at 21:55
  • NSURLConnection is not ideal, as the payload and headers get gzip'd (normally). So the number you get is mostly specious. That said, if the file you download is already zipped, then re-zipping will not change the size. – David H Sep 04 '12 at 22:34
  • Do you know some other way to do it in iOS? Maybe a more primitive way of downloading a file? – pedros Sep 04 '12 at 22:40
  • Check This Link It will full fill Your Requirements http://stackoverflow.com/questions/14532651/how-to-detect-network-signal-strenghth-in-ios-reachability – user3223527 Mar 10 '14 at 09:28

1 Answers1

2

As soon as you start the download, capture the current system time and store it as the startTime. Then, all you need to do is calculate data transfer speed at any point during the download. Just look at the system time again and use it as the currentTime to calculate the total time spent so far.

downloadSpeed = bytesTransferred / (currentTime - startTime)

Like this:

static NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];    
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
double downloadSpeed = totalBytesWritten / (currentTime - startTime);

You can use this method from NSURLConnectionDownloadDelegate:

- (void)connectionDidResumeDownloading:(NSURLConnection *)connection totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long) expectedTotalBytes;
Nishant
  • 12,529
  • 9
  • 59
  • 94