在網絡編程中,有幾個必須掌握的基本概念:php
URL的全稱是Uniform Resource Locator(統⼀資源定位符)html
經過1個URL,能找到互聯網上惟一的1個資源git
URL就是資源的地址、位置,互聯網上的每一個資源都有一個惟一的URLgithub
URL的基本格式 = 協議://主機地址/路徑http://61.144.56.195/forum/201302/19/144736txfrcuyvmustucmv.jpghttp://www.fzlu.com/uploads/allimg/140107/1-14010G22134235.jpgweb
解釋以下: 編程
a.HTTP:超文本傳輸協議,訪問的是遠程的網絡資源,格式是http:// http協議是在網絡開發中最經常使用的協議json
b.file:訪問的是本地計算機上的資源,格式是file://(不用加主機地址)api
c.mailto:訪問的是電子郵件地址,格式是mailto:瀏覽器
d.FTP:訪問的是共享主機的⽂文件資源,格式是ftp://緩存
網絡請求方式有兩種:GET 和 POST
兩種方式的相同點是:都能給服務器傳輸數據
兩種請求方式的不一樣點是:
2.3.1 給服務器傳輸數據的方式
GCT:經過網址字符串
POST:經過data
2.3.2 傳輸數據的大小
GET:網址字符串最多255字節
POST:使用NSData,容量超過1G
2.3.3 安全性
GET:全部傳輸給服務器的數據,顯示在網址裏,相似於密碼的明文輸入,直接可見
POST:數據被轉成NSData(二進制數據),相似於密碼的密文輸入,沒法直接讀取
鏈接方式
同步鏈接:程序容易出現卡死現象
(總結:同步鏈接請求可讓你可以從因特網請求數據,一旦發送同步請求後,程序將中止用戶交互,直至服務器返回數據完成纔可進行下一步操做。)
異步連接:等待數據返回
異步連接有兩種實現方式:1.設置代理,接受數據
2.實現block
GET的特色:
1. GET是"獲取"指定URL上的資源。
2. 其將數據按照varialbe = value的形式,添加action到所指向的URL後面,而且二者使用"?"鏈接,各個變量之間用"&"鏈接。
3. 不安全,由於在傳輸過程當中,數據被放在請求的URL中。這樣很容易被人拿到看見數據信息。
4.傳輸的數據量比較小
POST的特色:
1. POST語意是指對指定內容添加和追加數據(經過數據體的形式)
2. 將數據放在數據體中,按照變量和值相對應的方式,傳遞到action所指向的URL
3. 全部的數據對用戶不可見,也就是從URL中看不到。
4. 能夠傳輸大量數據,傳輸文件只能用POST
5. 不過對服務器來講,接收數據體可能會不安全
HTTP協議,Hyper Text Transfer Protocol (超文本傳輸協議)是用於從萬維網服務器傳送超文本到本地瀏覽器的傳輸協議,HTTP是一個應用層協議,由請求和響應構成,是一個標準的客戶端服務器模型。
HTTP協議的做⽤
HTTP的全稱是Hypertext Transfer Protocol,超文本傳輸協議
(1)規定客戶端和服務器之間的數據傳輸格式
(2)讓客戶端和服務器能有效地進行數據溝通
HTTP的通訊過程
要想使用HTTP協議向服務器索取數據,得先了解HTTP通訊的完整過程 完整的http通訊能夠分爲2大步驟
(1)請求:客戶端向服務器索要數據
(2)響應:服務器返回客戶端相應的數據
3.2.1 HTTP請求
HTTP協議規定,1個完整的由客戶端發給服務器的HTTP請求中包含如下內容
請求行:包含了請求方法、請求資源路徑、HTTP協議版本 GET /MJServer/resources/images/1.jpg HTTP/1.1
請求頭:包含了對客戶端的環境描述、客戶端請求的主機地址等信息
Host: 192.168.1.105:8080 // 客戶端想訪問的服務器主機地址
3.2.2 HTTP響應
客戶端向服務器發送請求,服務器應當作出響應,即返回數據給客戶端
HTTP協議規定:1個完整的HTTP響應中包含如下內容:
狀態行:包含了HTTP協議版本、狀態碼、狀態英⽂名稱HTTP/1.1 200 OK
響應頭:包含了對服務器的描述、對返回數據的描述 Server: Apache-Coyote/1.1 // 服務器的類型
Content-Type: image/jpeg // 返回數據的類型
Content-Length: 56811 // 返回數據的長度
Date: Mon, 23 Jun 2014 12:54:52 GMT // 響應的時間 實體內容:服務器返回給客戶端的具體數據,⽐好比⽂件數據
發送HTTP請求的⽅法
在HTTP/1.1協議中,定義了8種發送http請求的⽅方法 GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH 根據HTTP協議的設計初衷,不一樣的方法對資源有不一樣的操做⽅方式
PUT :增
DELETE :刪
POST:改
GET:查 提示:最經常使用的是GET和POST(實際上GET和POST都能辦到增刪改查)
get和post的選擇
(1)若是要傳遞大量數據,⽐如⽂件上傳,只能用POST請求
(2)GET的安全性比POST要差些,若是包含機密\敏感信息,建議⽤用POST
(3)若是僅僅是索取數據(數據查詢),建議使用GET
(4)若是是增長、修改、刪除數據,建議使用POST
• 構造NSURL實例(地址)
• ⽣成NSURLRequest請求(網絡請求的信息)
• 經過NSURLConnection發送請求
• 經過返回NSURLRespond實例和NSError實例分析結果
• 處理返回數據
3.3.1 GET請求
GET請求:獲取數據,把參數以URL的形式拼接傳給服務器,以 ? 分開URL地址和參數,& 拼接多個參數
1.建立一個URL
NSString *urlStr = @"https://route.showapi.com/213-4?showapi_appid=24110&showapi_timestamp=20160905154834&topid=5&showapi_sign=5d1ba1725827501e32238072e5960958"; NSURL *URL = [NSURL URLWithString:urlStr];
2.建立一個NSURLRequest 請求
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
三、建立NSURLSession
NSURLSession *session = [NSURLSession sharedSession];
四、由session建立一個請求數據的任務NSURLSessionDataTask(會以異步的形式發送網絡請求,不會阻塞主線程)
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 執行完後 以block 返回結果,解析數據 id jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",jsonData); }];
五、開始執行網絡任務
[dataTask resume];
3.3.2 POST請求
POST請求時要指明請求的方式HTTPMethod 爲 POST,參數以請求體 HTTPMethod 的形式傳入。
一、設置請求方式爲 POST
NSURL *url = [NSURL URLWithString:@"https://route.showapi.com/213-4"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST";
二、設置請求體:把參數做爲NSData類型傳入
NSString *parmStr = [NSString stringWithFormat:@"showapi_appid=%@&showapi_timestamp=%@&topid=%@&showapi_sign=%@",APPID,@"20160905154834",@"5",SIGN]; request.HTTPBody = [parmStr dataUsingEncoding:NSUTF8StringEncoding];
3.建立一個NSURLRequest 請求
NSURLSession *session = [NSURLSession sharedSession];
四、由session建立一個請求數據的任務NSURLSessionDataTask(會以異步的形式發送網絡請求,不會阻塞主線程)
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"%@",error); return; } // NSLog(@"%@",response); // 執行完後 以block 返回結果,解析數據 id jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",jsonData); }]; //開始執行網絡請求 [dataTask resume];
NSURLRequest的cachePolicy屬性能夠設置緩存策略,這是⼀種內存緩存,⾮硬盤緩存。使用緩存的目的是爲了使⽤的應用程序能更快速的響應⽤戶輸入,使程序高效的運行。有時候咱們須要將遠程web服務器獲取的數據緩存起來,減小對同⼀個url屢次請求。
// 默認,使用緩存,當下一次請求時先判斷是否有緩存,有就使用緩存沒有才進行網絡請求,使用緩存時會先判斷緩存是否過時,過時的就從新請求網絡。 NSURLRequestUseProtocolCachePolicy = 0, // 忽略緩存,不使用緩存 NSURLRequestReloadIgnoringLocalCacheData = 1, // 無視任何的緩存策略,不管是本地的仍是遠程的,老是從原地址從新下載 NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData, //首先使用緩存不論是否過時,若是沒有本地緩存,才從原地址下載 NSURLRequestReturnCacheDataElseLoad = 2, //使用本地緩存,從不下載,若是本地沒有緩存,則請求失敗。此策略多用於離線操做 NSURLRequestReturnCacheDataDontLoad = 3, //緩存數據必須得獲得服務端確認有效才使用(NSURLRequestUseProtocolCachePolicy中的一種狀況) // Unimplemented NSURLRequestReloadRevalidatingCacheData = 5,
timeoutInterval: 設置請求超時的時間秒數
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10];
NSURLSessionConfiguration:配置網絡請求
// 默認的模式,能夠緩存數據(默認會話模式) defaultSessionConfiguration, //無痕瀏覽,不會有任何的緩存(瞬間會話模式) ephemeralSessionConfiguration, //後臺會話模式(該模式在後臺完成上傳和下載,在建立Configuration對象的時候須要提供一個NSString類型的ID用於標識完成工做的後臺會話。) backgroundSessionConfigurationWithIdentifier NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
經過 NSURLSessionConfiguration 設置緩存策略
configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSession是爲了代替NSURLConnection而設計的。Sessions的全部工做都是經過NSURLSessionTask (NSURLsessionTask 是一個抽象類,其中有 3 個實體子類能夠直接使用:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。這 3 個子類封裝了現代程序三個最基本的網絡任務:獲取數據,好比 JSON 或者 XML,上傳文件和下載文件。)實現的。可使用block,delegate,或者二者混合來建立task。(舉個例子,你要下載圖片,就要建立NSURLSessionDownloadTask。)
建立URL
NSURL *url = [NSURL URLWithString:@"http://dl.stream.qqmusic.qq.com/108051051.mp3?vkey=4A95A0FCDFDC050E9D543841CA4A28AABD19F1973177DAB509EEBED09344D0A91A286D0800E7C58751A670CC429DB1118C98F8908C487284&guid=2718671044"];
建立Session並設置
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
建立一個下載任務
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { return; } // 設置保存文件的本地URL NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; //拼接一個數據名,response suggestedFilename 自動獲取下載數據的名字.格式類型 NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:[response suggestedFilename]]; NSError *moveError = nil; // 將下載的數據從臨時URL移動到指定的URL [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError]; if (!moveError) { NSLog(@"保存成功"); } NSLog(@"%@",location); }];
啓動下載
[downloadTask resume];
代理的方式下載
NSURL *url = [NSURL URLWithString:@"https://github.com/AFNetworking/AFNetworking/archive/master.zip"]; //配置NSURLSession並設置代理,delegateQueue:代理執行的線程 NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *downTask = [session downloadTaskWithURL:url]; // 啓動下載 [downTask resume];
下載完成後調用
//下載完成後調用 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"下載完成 %@",NSHomeDirectory()); // 設置保存文件的本地URL NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:downloadTask.response.suggestedFilename]; NSError *moveError = nil; //將下載的數據從臨時URL移動到指定的URL [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError]; if (!moveError) { NSLog(@"保存成功"); } }
監聽下載進度
// 監聽下載進度 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { // bytesWritten: 時間點下載的數據大小 totalBytesWritten:已經下載的數據大小,totalBytesExpectedToWrite: 下載文件的總大小 self.prograssView.prograss = (CGFloat)totalBytesWritten / (CGFloat)totalBytesExpectedToWrite; NSLog(@"%lld, %lld, %lld ",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); }
文件上傳也有block和代理兩種方式
block方式上傳
建立URL
NSURL *url = [NSURL URLWithString:@"http://www.imageshack.us/index.php"];
建立請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];
設置請求爲POST
request.HTTPMethod = @"POST";
設置請求頭的上傳文件的內容格式(Content-Type) 爲圖片類型(image/jpeg)
[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];
設置請求頭的響應(Accept)的文本格式(text/html)
[request setValue:@"text/html" forHTTPHeaderField:@"Accept"]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
上傳方式一:把要上傳的數據保存爲NSData
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"image7.jpeg"], 0.5); NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"%@",error); } else { NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@ \n%@",response, reuslt); } }];
上傳方式二:使用文件所在的本地的URL
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"image7" withExtension:@"jpeg"]; // NSURL *fileURL = [NSURL URLWithString:@"http://img.ivsky.com/img/tupian/pre/201507/01/yindian_meinv-001.jpg"]; NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"%@",error); } else { NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@ \n%@",response, reuslt); } }]; // 恢復線程,啓動任務 [uploadTask resume];
NSURLSession 支持程序的後臺下載和上傳, 蘋果官方將其稱之進程以外的上傳和下載, 這些任務都交給後臺守護線程完成, 而不是應用自己, 即便文件在下載和上傳過程當中崩潰了也能夠繼續運行(若是用戶強制關閉程序的話, NSURLSession會斷開鏈接)
簽定代理協議
@interface ViewController ()<NSURLSessionDownloadDelegate>
建立URL和請求
NSURL *url = [NSURL URLWithString:@"https://github.com/fuqinglin/MagicalRecord/archive/master.zip"]; NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];
設置網絡請求爲 backgroundSessionConfigurationWithIdentifier 後臺模式,後面接標識符
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.tens.background"];
建立NSURLSession
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
啓動下載任務
[downloadTask resume];
// 後臺下載完調用 - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { NSLog(@"後臺下載完成"); AppDelegate *delegate = [UIApplication sharedApplication].delegate; // 回調 AppDelegate 中 application: handleEventsForBackgroundURLSession: completionHandler: 中的block事件,處理下載完後的提示 if (delegate.backgroundCompletionHandler) { void (^completionHandler)() = delegate.backgroundCompletionHandler; completionHandler(); } }
NSURLSessionDownloadTask支持取消下載,能夠在下載過程當中隨時取消繼續下載,同時也能夠實現恢復下載。
取消下載 cancelByProducingResumeData
//用當前NSURLSessionDownloadTask對象去調用取消下載 [self.downTask cancelByProducingResumeData: ^(NSData * _Nullable resumeData) { //全局變量 接收當前下載的資源 self.data = resumeData; } //將當前下載任務置爲空 self.downTask = nil;
恢復下載 downloadTaskWithResumeData
//恢復下載 其實是創建了一個新的下載任務 去繼續以前的下載 self.downTask = [self.downLoadSession downloadTaskWithResumeData:self.data]; //開啓任務 [self.downTask resume]; }