Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep a connection alive using ASIHTTP? I need to make multiple requests, but can't afford to open, then close a request connection

I have a method that I call to make web service requests using GET. It looks like this:

- (UIImage*)getImageWithSeriesGUID:(NSString*)seriesGUID ImageID:(int)imageID {

NSString * unescapedString = RIVERWOODS_GET_IMAGE(seriesGUID, imageID);

NSURL *url = [[NSURL alloc] initWithString:[unescapedString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];


ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

[request setRequestMethod:@"GET"];
[request addRequestHeader:@"Connection" value:@"Keep-Alive"];

[request startSynchronous];
NSError *error = [request error];
if (!error) {
    NSData *response = [request responseData];
    //NSLog(@"Size: %@",[response length]);
    NSString *content = [[[NSString alloc] initWithData:response
                                               encoding:NSUTF8StringEncoding] autorelease];
    NSLog(@"Data: %@", content);
    UIImage *image = [UIImage imageWithData:response];
    return image;
}

return nil;
 }

This approach works ok, but it is just REALLY slowly. On the other end I am iterating through a for loop so this method gets called 20 times if the picture array I need to collect has 20 images. I am looking to improve the efficiency of this process, and I am thinking that I should be able to iterate through all the image Id's I need to collect right here in this method.

It seems to me that the reason this goes so slowly is because the multiple requests that we keep opening and closing. THe images I am pulling in are on average ~15kb.

My question: What can I do to change this method around to make it so I can improve efficiency and take advantage of the HTTP keep-alive features? I am thinking that instead of passing in an image ID, I can just pass in the count of the array I need to make, and then setup a for-loop of some sorts here in the request method which would then allow me to pass back an array of images...

Is that the way to go? Is there something I am missing? I appreciate your help and input!!

like image 518
Stephen J. Avatar asked Jan 24 '26 09:01

Stephen J.


1 Answers

The reason why this is slow as hell is that you're doing the requests synchronously (which is always a no-no anyway), one-by-one. You need to refactor your download method to work asynchronously, and concurrently.

My approach to requesting data on the wire in that manner is as follows:

  • Create a global network connection 'controller' (accessible from your App Delegate), which can create an ASINetworkQueue on the fly when required and release it when no requests remain
  • Wrap your requests into a subclass of ASIHTTPRequest, and override the done/fail methods in those subclasses (make them fire a notification with returned data if you like; or write to disk and update a db with their reference).
  • For every request, grab the queue reference, and add your request to the queue.
  • The queue will grow and shrink as needed

If I were at my computer I'd check into github an example of this, but really the only difficult part is the global connection manager, and the ASI* guys have written a great example here on gist.github. Also, a better explanation of the above (where I learnt it from) is here.

like image 73
Alan Zeino Avatar answered Jan 26 '26 11:01

Alan Zeino



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!