iOS Network programming: HTTP
HTTP defines a way to pass data between a server and a client.
A URL defines a way to uniquely identify the location of a resource in a network.
Requests and Responses:
The client first establishes a TCP connection and then sends a request. The server sends a response to the client to pass the data after it is processed by the request. The client can then continue to send the request or close the TCP connection.
HTTPS:
After a TCP connection is established, an SSL session needs to be established before the request is sent.
The request method and their purpose
iOS nsurlrequest and its subclass nsmutableurlrequest provide a way to establish an HTTP request.
Nsurlresponse and its subclasses Nshttpurlresponse to process the returned data.
Url:
Protocol includes HTTP, FTP, and file.
URL encoding:
NSString *encoded = [URLString stringbyaddingpercentescapesusingencoding:nsutf8stringencoding];
Nsurl is used to manage URLs.
IOS HTTP APIS:
Some of the following classes are involved:
Nsurl,nsurlrequest, Nsurlconnection, and Nsurlresponse.
1, Nsurl
Nsurl can define local files and network files
NSData *data = [NSData Datawithcontentsofurl:url];
Nsurl defines a number of accessors:
NSLog (@ "Port is nil"); else {NSLog (@ "Port is not nil");}
2, Nsurlrequest
Once you have created Nsurl, you can create a request with Nsurlrequest:
Nsurl *url = [Nsurl urlwithstring: @ "https://gdata.youtube.com/feeds/api/standardfeeds/top_rated"];if (url = = nil) {
if (request = = nil) {NSLog (@ "Invalid request"); Return }
Nsmutableurlrequest is a subclass of Nsurlrequest that provides a way to change the properties of a request:
[Req sethttpmethod:@ "POST"]; [Req sethttpbody:[@ "Post body" datausingencoding:nsutf8stringencoding]];
If you want to send a picture or video, then use Nsinputstream, it does not add all the data to the memory.
Nsmutableurlrequest *request = [Nsmutableurlrequest Requestwithurl:url]; Nsinputstream *instream = [Nsinputstream Inputstreamwithfileatpath:srcfilepath]; [Request Sethttpbodystream:instream]; [Request sethttpmethod:@ "POST"];
3, Nsurlconnection
Provides initialization, start, and cancellation of a connection.
4,Nsurlresponse
To send a sync request:
-(Nsarray *) Dosyncrequest: (NSString *) urlstring {//Make the Nsurl object from the string Nsurl *url = [nsurl URL Withstring:urlstring]; Create the Request object with a second timeout and a cache policy to always retrieve the//feed regardless of C Achability. Nsurlrequest *request = [Nsurlrequest requestwithurl:url Cachepolicy:nsurlrequestreloadigno Ringlocalandremotecachedata timeoutinterval:30.0]; Send the request and wait for a response nshttpurlresponse *response; Nserror *error; NSData *data = [nsurlconnection sendsynchronousrequest:request returningresponse: &response error:&error]; Check for an error if (Error! = nil) {NSLog (@ "error on load =%@", [Error localizeddescription]); return nil; }//Check the HTTP status if ([Response IsKIndofclass:[nshttpurlresponse class]] {nshttpurlresponse *httpresponse = (Nshttpurlresponse *) response; if (httpresponse.statuscode! =) {return nil; } NSLog (@ "Headers:%@", [HttpResponse allheaderfields]); }//Parse the data returned into an nsdictionary nsdictionary *dictionary = [XMLReader dictionaryforxml Data:data error:&error]; Dump the dictionary to the log file NSLog (@ "feed =%@", dictionary); Nsarray *entries =[self Getentriesarray:dictionary]; Return the list if items from the feed. return entries;}
Queued Asynchronous requests:
-(void) Doqueuedrequest: (NSString *) urlstring delegate: (ID) delegate {//Make the Nsurl object nsurl *url = [Nsurl Urlwithstring:urlstring]; Create the Request object with a no cache policy and a second timeout. Nsurlrequest *request = [Nsurlrequest requestwithurl:url cachepolicy: Nsurlrequestreloadignoringlocalandremotecachedata timeoutinterval:30.0]; If the queue doesn ' t exist, create one. if (queue = = nil) {queue = [[Nsoperationqueue alloc] init]; }//Send the request and specify the code to execute when the request completes or fails. [Nsurlconnection sendasynchronousrequest:request Queue:queue completionhandler:^ (Nsurlresponse *response, NSData *data, Nserror *error) {if (Error! = nil) { NSLog (@ "Error on load = %@ ", [Error localizeddescription]); } else {//check the HTTP status if ([Response Iskindofclass:[nshttpurlresp Onse class]] {nshttpurlresponse *httpresponse = (Nshttpurlresponse *) response; if (httpresponse.statuscode! =) {return; } NSLog (@ "Headers:%@", [HttpResponse allheaderfields]); }//Parse the results and make a dictionary nsdictionary *di Ctionary = [XMLReader dictionaryforxmldata:data error:& ; error]; NSLog (@ "feed =%@", dictionary); Get the dictionary entries. Nsarray *entries =[self Getentriesarray:dictionary]; Call the delegate if ([Delegate respondstoselector: @selector (Setvideos:)]) { [Delegate Performselectoronmainthread: @selector (setvideos:) wit Hobject:entries Waituntildone:yes]; } } }];}
Asynchronous requests:
#import <Foundation/Foundation.h> #define Kdownloadcomplete @ "DownloadComplete" @class downloadprogressview;@ Interface Asyncdownloader:nsobject <NSURLConnectionDelegate> {//The number of bytes that need to be downloade D Long Long downloadsize; The total amount downloaded thus long long totaldownloaded;} A reference to the Progress view to show the user how things is progressing@property (assign) Downloadprogressview *PR ogressview;//the target MP4 file@property (strong) NSString *targetfile;//the original URL to download. Due to redirects the actual content could come from another url@property (strong) NSString *srcurl;//the open file to which The content is Written@property (strong) Nsfilehandle *outputhandle;//the name of the temp file to which the content is Streamed. This file was moved to the target file when//the download is Complete@property (strong) NSString *tempfile; @property (Stro NG) Nsurlconnection *conn;//instructs the class toStart the download.-(void) start; @end
asyncdownloader.m//videodownloader////Created by Jack Cox on 4/7/12.////#import "AsyncDownloader.h" #import "D OwnloadProgressView.h "@implementation asyncdownloader@synthesize targetfile; @synthesize Srcurl; @synthesize Outputhandle, @synthesize tempfile; @synthesize progressview; @synthesize conn;-(void) Start {NSLog (@ "Starting to Downlo Ad%@ ", Srcurl); Create the URL nsurl *url = [Nsurl Urlwithstring:srcurl]; Create the request nsurlrequest *request = [Nsurlrequest Requestwithurl:url]; Create the connection with the target request and this class as the delegate self.conn = [Nsurlconnection C Onnectionwithrequest:request Delegate:self]; Start the connection [Self.conn start];} /** * Creates a UUID to use as the temporary file name during the download */-(NSString *) createuuid{cfuuidref Uuidre f = cfuuidcreate (NULL); Cfstringref uuidstringref = cfuuidcreatestring (NULL, UUIDREF); Cfrelease (UUIDREF); NSString *uuid = [NSString stringwithstring: (__bridge NSString *) uuidstringref]; Cfrelease (UUIDSTRINGREF); return UUID;} #pragma mark Nsurlconnectiondelegate methods/** * This delegate method was called when the nsurlconnection gets a-serie s response that indicates * so the request needs to be redirected. It is implemented-to-display any redirects that might * occur. This method is optional. If omitted the client would follow all redirects. **/-(Nsurlrequest *) connection: (Nsurlconnection *) connection willsendrequest: (nsurlrequest *) request Redirectresponse: (Nsurlresponse *) redirectresponse {//Dump Debugging Information NSLog (@ "Redirect request For%@ redirecting to%@ ", Srcurl, request. URL); NSLog (@ "All headers =%@", [(nshttpurlresponse*) Redirectresponse allheaderfields]); Follow the redirect return request;} /** * This delegate method was called whenThe nsurlconnection connects to the server. It contains the * Nsurlresponse object with the headers returned by the server. This method is called multiple times. * Therefore, it is important to reset the data on each call. Do not assume the It is the first call * of this method. **/-(void) connection: (Nsurlconnection *) connection didreceiveresponse: (Nsurlresponse *) Response {NSLog (@ "Received R Esponse from request to URL%@ ", srcurl); Nshttpurlresponse *httpresponse = (Nshttpurlresponse *) response; NSLog (@ "All headers =%@", [HttpResponse allheaderfields]); if (httpresponse.statuscode! =) {//something went wrong, abort the whole thing//reset the download counts if (downloadsize! = 0L) {[Progressview addamounttodownload:-downloadsize]; [Progressview addamountdownloaded:-totaldownloaded]; } [connection Cancel]; Return } Nsfilemanager *fm = [Nsfilemanager Defaultmanager];If we have a temp file already, close it and delete it if (self.tempfile! = nil) {[Self.outputhandle Closefi Le]; Nserror *error; [FM RemoveItemAtPath:self.tempFile error:&error]; }//Remove any pre-existing target file Nserror *error; [FM Removeitematpath:targetfile error:&error]; Get the temporary directory name and make a temp file name nsstring *tempdir = Nstemporarydirectory (); Self.tempfile = [TempDir stringbyappendingpathcomponent:[self createuuid]]; NSLog (@ "Writing content to%@", self.tempfile); Create and open the temporary file [FM createFileAtPath:self.tempFile Contents:nil Attributes:nil]; Self.outputhandle = [Nsfilehandle fileHandleForWritingAtPath:self.tempFile]; Prime the download progress view nsstring *contentlengthstring = [[HttpResponse allheaderfields] objectforkey:@ "Cont Ent-length "]; Reset the download counts if (downloadsize! = 0L) {[PROGRESSVIEW Addamounttodownload:-downloadsize]; [Progressview addamountdownloaded:-totaldownloaded]; } downloadsize = [contentlengthstring longlongvalue]; totaldownloaded = 0L; [Progressview addamounttodownload:downloadsize];} /** * This delegate method are called for each chunk of data received from the server. The chunk size * is dependent on the network type and the server configuration. */-(void) connection: (Nsurlconnection *) connection didreceivedata: (NSData *) data {//figure out what many bytes in This chunk totaldownloaded+=[data length]; Uncomment if you want a packet by packet log of the bytes received. NSLog (@ "Received%lld of%lld (%f%%) bytes of data for URL%@", totaldownloaded, Downloadsize, (double) totaldownloaded/(double) downloadsize) *100.0, Srcurl); Inform the progress view that data is downloaded [progressview addamountdownloaded:[data length]]; Save the bytes ReceivEd [Self.outputhandle Writedata:data];} /** * This delegate methodis called if the connection cannot is established to the server. * The Error object would have a description of the error **/-(void) connection: (Nsurlconnection *) connection didfailwithe Rror: (Nserror *) error {NSLog (@ "Load failed with Error%@", [Error localizeddescription]); Nsfilemanager *FM = [Nsfilemanager Defaultmanager]; If we have a temp file already, close it and delete it if (self.tempfile! = nil) {[Self.outputhandle Closefi Le]; Nserror *error; [FM RemoveItemAtPath:self.tempFile error:&error]; }//Reset the Progress View if (downloadsize! = 0L) {[Progressview addamounttodownload:-downloadsize]; [Progressview addamountdownloaded:-totaldownloaded]; }}/** * This delegate method was called when the data load was complete. The delegate is released * Following this call **/-(void) connectiondidfinishloading: (NSURLConnection *) connection {//close the file [Self.outputhandle CloseFile]; Move the file to the target location nsfilemanager *fm = [Nsfilemanager Defaultmanager]; Nserror *error; [FM moveItemAtPath:self.tempFile ToPath:self.targetFile error:&error]; Notify any concerned classes that the download are complete [[Nsnotificationcenter Defaultcenter] Postnotificati Onname:kdownloadcomplete Object:nil Userinfo:nil];} @end
iOS Network programming: HTTP