iOS 網絡編程

 

1、網絡編程的基本概念

在網絡編程中,有幾個必須掌握的基本概念:php

  • 客戶端(Client):移動應⽤(iOS,Andorid等應⽤)
  • 服務器(Server):爲客戶端提供服務、提供數據、提供資源的機器
  • 請求(Request):客戶端向服務器索取數據的⼀種行爲
  • 響應(Response):服務器對客戶端的請求作出的反應,通常指返回數據給客戶端

2、URL

2.1 基本介紹

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

解釋以下: 編程

  • 協議:不一樣的協議,表明着不一樣的資源查找方式、資源傳輸方式,好比經常使用的http,ftp等
  • 主機地址:存放資源的主機的IP地址(域名)
  • 路徑:資源在主機中的具體位置
  • 參數:參數無關緊要,也能夠多個。若是帶參數的話,用「?」號後面接參數,多個參數的話之間用&隔開

2.2 URL中常見的協議

a.HTTP:超文本傳輸協議,訪問的是遠程的網絡資源,格式是http:// http協議是在網絡開發中最經常使用的協議json

b.file:訪問的是本地計算機上的資源,格式是file://(不用加主機地址)api

c.mailto:訪問的是電子郵件地址,格式是mailto:瀏覽器

d.FTP:訪問的是共享主機的⽂文件資源,格式是ftp://緩存

2.3 URL的請求方式

網絡請求方式有兩種: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

2.4 總結GET的特色和POST的特色

GET的特色:

1. GET是"獲取"指定URL上的資源。

2. 其將數據按照varialbe = value的形式,添加action到所指向的URL後面,而且二者使用"?"鏈接,各個變量之間用"&"鏈接。

3. 不安全,由於在傳輸過程當中,數據被放在請求的URL中。這樣很容易被人拿到看見數據信息。

4.傳輸的數據量比較小

POST的特色:

1. POST語意是指對指定內容添加和追加數據(經過數據體的形式)

2. 將數據放在數據體中,按照變量和值相對應的方式,傳遞到action所指向的URL

3. 全部的數據對用戶不可見,也就是從URL中看不到。

4. 能夠傳輸大量數據,傳輸文件只能用POST

5. 不過對服務器來講,接收數據體可能會不安全

 3、HTTP協議

3.1 HTTP協議的概念

HTTP協議,Hyper Text Transfer Protocol (超文本傳輸協議)是用於從萬維網服務器傳送超文本到本地瀏覽器的傳輸協議,HTTP是一個應用層協議,由請求和響應構成,是一個標準的客戶端服務器模型。

HTTP協議的做⽤

HTTP的全稱是Hypertext Transfer Protocol,超文本傳輸協議

(1)規定客戶端和服務器之間的數據傳輸格式

(2)讓客戶端和服務器能有效地進行數據溝通

HTTP的通訊過程

要想使用HTTP協議向服務器索取數據,得先了解HTTP通訊的完整過程 完整的http通訊能夠分爲2大步驟

(1)請求:客戶端向服務器索要數據

(2)響應:服務器返回客戶端相應的數據

3.2 HTTP通訊過程:請求和響應

3.2.1 HTTP請求

HTTP協議規定,1個完整的由客戶端發給服務器的HTTP請求中包含如下內容

  • 請求行:包含了請求方法、請求資源路徑、HTTP協議版本 GET /MJServer/resources/images/1.jpg HTTP/1.1

  • 請求頭:包含了對客戶端的環境描述、客戶端請求的主機地址等信息

  • Host: 192.168.1.105:8080 // 客戶端想訪問的服務器主機地址

  • User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客戶端的 類型,客戶端的軟件環境
  • Accept: text/html, /// 客戶端所能接收的數據類型 Accept-Language: zh-cn // 客戶端的語言環境
  • Accept-Encoding: gzip // 客戶端支持的數據壓縮格式 請求體:客戶端發給服務器的具體數據,好比文件數據

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

3.3 http請求的基本流程

• 構造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];

4、緩存策略(NSURLRequestCachePolicy) 

4.1 緩存策略基本概念

NSURLRequest的cachePolicy屬性能夠設置緩存策略,這是⼀種內存緩存,⾮硬盤緩存。使用緩存的目的是爲了使⽤的應用程序能更快速的響應⽤戶輸入,使程序高效的運行。有時候咱們須要將遠程web服務器獲取的數據緩存起來,減小對同⼀個url屢次請求。

4.2 設置緩存策略:cachePolicy

// 默認,使用緩存,當下一次請求時先判斷是否有緩存,有就使用緩存沒有才進行網絡請求,使用緩存時會先判斷緩存是否過時,過時的就從新請求網絡。
     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];

5、NSURLSession下載與上傳

5.1 NSURLSession基本概念

  NSURLSession是爲了代替NSURLConnection而設計的。Sessions的全部工做都是經過NSURLSessionTask (NSURLsessionTask 是一個抽象類,其中有 3 個實體子類能夠直接使用:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。這 3 個子類封裝了現代程序三個最基本的網絡任務:獲取數據,好比 JSON 或者 XML,上傳文件和下載文件。)實現的。可使用block,delegate,或者二者混合來建立task。(舉個例子,你要下載圖片,就要建立NSURLSessionDownloadTask。)

5.2 block方式下載

建立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);
}

5.2 文件上傳

文件上傳也有block和代理兩種方式

  • 文件上傳的時候須要設置請求頭中Content-Type類型, 必須使用URL編碼

 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];

6、後臺下載

6.1 後臺下載的基本概要

 NSURLSession 支持程序的後臺下載和上傳, 蘋果官方將其稱之進程以外的上傳和下載, 這些任務都交給後臺守護線程完成, 而不是應用自己, 即便文件在下載和上傳過程當中崩潰了也能夠繼續運行(若是用戶強制關閉程序的話, NSURLSession會斷開鏈接)

6.2 後臺下載代碼以下

簽定代理協議

@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();
    
    }
}

6.3 拓展知識點

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];
    
        }
相關文章
相關標籤/搜索