標籤:des blog http io ar os sp for strong
IOS網路編程:HTTP
HTTP定義了一種在伺服器和用戶端之間傳遞資料的途徑。
URL定義了一種唯一標示資源在網路中位置的途徑。
REQUESTS 和 RESPONSES:
用戶端先建立一個TCP串連,然後發送一個請求。伺服器受到請求處理後發送一個響應向用戶端傳遞資料。然後用戶端可以繼續發送請求或者關閉這個TCP串連。
HTTPS:
在TCP串連建立後,發送請求之前,需要建立一個一個SSL會話。
request方法和它們的用途
iOS的NSURLRequest和它的子類NSMutableURLRequest提供了建立HTTP請求的方法。
NSURLResponse 和 它的子類NSHTTPURLResponse 處理返回的資料。
URL:
Protocol包括HTTP、FTP和file。
URL編碼:
NSString *urlString = @"http://myhost.com?query=This is a question";
NSString *encoded = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL用來管理URL。
IOS HTTP APIS:
涉及到下面一些類:
NSURL, NSURLRequest, NSURLConnection, 和 NSURLResponse.
1、NSURL
NSURL可以定義本地檔案和網路檔案
NSURL *url = [NSURL urlWithString:@"http://www.google.com"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSURL定義了很多訪問器:
if (url.port == nil) {
NSLog(@"Port is nil");} else { NSLog(@"Port is not nil");}
2、NSURLRequest
建立了NSURL後,就可以用NSURLRequest建立請求了:
NSURL *url = [NSURL URLWithString: @"https://gdata.youtube.com/feeds/api/standardfeeds/top_rated"];if (url == nil) { NSLog(@"Invalid URL");
return;}NSURLRequest *request = [NSURLRequest requestWithURL:url];
if (request == nil) { NSLog(@"Invalid Request"); return; }
NSMutableURLRequest是NSURLRequest 的子類,提供了改變請求的屬性的方法:
NSURL *url = [NSURL [email protected]"http://server.com/postme"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req setHTTPMethod:@"POST"];[req setHTTPBody:[@"Post body" dataUsingEncoding:NSUTF8StringEncoding]];
如果你要發送一個圖片或者視頻,那麼用需要用NSInputStream,它沒有把資料全部加在到記憶體。
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];NSInputStream *inStream = [NSInputStream inputStreamWithFileAtPath:srcFilePath];[request setHTTPBodyStream:inStream];[request setHTTPMethod:@"POST"];
3、NSURLConnection
提供了初始化、開始、和取消一個串連。
4、NSURLResponse
發送同步請求:
- (NSArray *) doSyncRequest:(NSString *)urlString { // make the NSURL object from the string NSURL *url = [NSURL URLWithString:urlString]; // Create the request object with a 30 second timeout and a cache policy to always retrieve the // feed regardless of cachability. NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData 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 != 200) { return nil; } NSLog(@"Headers: %@", [httpResponse allHeaderFields]); } // Parse the data returned into an NSDictionary NSDictionary *dictionary = [XMLReader dictionaryForXMLData: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 30 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:[NSHTTPURLResponse class]]) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if (httpResponse.statusCode != 200) { return; } NSLog(@"Headers: %@", [httpResponse allHeaderFields]); } // parse the results and make a dictionary NSDictionary *dictionary = [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:) withObject: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 downloaded long long downloadSize; // the total amount downloaded thus far long long totalDownloaded;}// A reference to the progress view to show the user how things are progressing@property (assign) DownloadProgressView *progressView;// The target MP4 file@property (strong) NSString *targetFile;// The original URL to download. Due to redirects the actual content may 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 is moved to the target file when// the download is complete@property (strong) NSString *tempFile;@property (strong) NSURLConnection *conn;// instructs the class to start the download.- (void) start;@end
//// AsyncDownloader.m// VideoDownloader//// Created by Jack Cox on 4/7/12.// //#import "AsyncDownloader.h"#import "DownloadProgressView.h"@implementation AsyncDownloader@synthesize targetFile;@synthesize srcURL;@synthesize outputHandle;@synthesize tempFile;@synthesize progressView;@synthesize conn;- (void) start { NSLog(@"Starting to download %@", 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 connectionWithRequest: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 uuidRef = 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 is called when the NSURLConnection gets a 300 series response that indicates * that the request needs to be redirected. It is implemented here to display any redirects that might * occur. This method is optional. If omitted the client will 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 is called when the NSURLConnection connects to the server. It contains the * NSURLResponse object with the headers returned by the server. This method may be called multiple times. * Therefore, it is important to reset the data on each call. Do not assume that it is the first call * of this method. **/- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"Received response from request to url %@", srcURL); NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; NSLog(@"All headers = %@", [httpResponse allHeaderFields]); if (httpResponse.statusCode != 200) {// 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 closeFile]; 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:@"Content-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 is 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 how 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 be established to the server. * The error object will have a description of the error **/- (void)connection:(NSURLConnection *)connection didFailWithError:(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 closeFile]; NSError *error; [fm removeItemAtPath:self.tempFile error:&error]; } // reset the progress view if (downloadSize != 0L) { [progressView addAmountToDownload:-downloadSize]; [progressView addAmountDownloaded:-totalDownloaded]; }}/** * This delegate method is called when the data load is complete. The delegate will be 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 is complete [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadComplete object:nil userInfo:nil];}@end
IOS網路編程:HTTP