HTTP和GET/POST請求(NSURLConnection)

来源:http://www.cnblogs.com/chao8888/archive/2016/06/17/5594380.html
-Advertisement-
Play Games

網路編程 網路編程是一種實時更新應用數據的常用手段 網路編程是開發優秀網路應用的前提和基礎 網路基本概念 客戶端(就是手機或者ipad等手持設備上面的APP) 伺服器(遠程伺服器 本地伺服器) 請求(客戶端索要數據的方式) 響應(需要客戶端解析數據) 資料庫(伺服器的數據從哪裡來) HTTP URL ...



  • 網路編程
  • 網路編程是一種實時更新應用數據的常用手段
  • 網路編程是開發優秀網路應用的前提和基礎

  • 網路基本概念
  • 客戶端(就是手機或者ipad等手持設備上面的APP)
  • 伺服器(遠程伺服器-本地伺服器)
  • 請求(客戶端索要數據的方式)
  • 響應(需要客戶端解析數據)
  • 資料庫(伺服器的數據從哪裡來)

HTTP


URL

  • 如何找到伺服器(通過一個唯一的URL)
  • URL介紹
  • 統一資源定位符
  • url格式(協議\主機地址\路徑)
    • 協議:不同的協議,代表著不同的資源查找方式、資源傳輸方式
    • 主機地址:存放資源的主機(伺服器)的IP地址(功能變數名稱)
    • 路徑:資源在主機(伺服器)中的具體位置
  • 請求協議
  • 【file】訪問的是本地電腦上的資源,格式是file://(不用加主機地址)
  • 【ftp】訪問的是共用主機的文件資源,格式是ftp://
  • 【mailto】訪問的是電子郵件地址,格式是mailto:
  • 【http】超文本傳輸協議,訪問的是遠程的網路資源,格式是http://(網路請求中最常用的協議)

HTTP協議

  • 簡介
  • a.超文本傳輸協議
  • b.規定客戶端和伺服器之間的數據傳輸格式
  • c.讓客戶端和伺服器能有效地進行數據溝通

  • 優缺點
  • a.簡單快速(協議簡單,伺服器端程式規模小,通信速度快)
  • b.靈活(允許傳輸各種數據)
  • c.非持續性連接(1.1之前版本是非持續的,即限制每次連接只處理一個請求,伺服器對客戶端的請求做出響應後,馬上斷開連接,這種方式可以節省傳輸時間)
  • 基本通信過程
  • a.請求:客戶端向伺服器索要數據
  • b.響應:伺服器返回客戶端相應的數據

GET和POST請求


  • HTTP裡面發送請求的方法
  • GET(常用)、POST(常用)、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH

  • GET和POST請求的對比【區別在於參數如何傳遞】
  • GET
    • 在請求URL後面以?的形式跟上發給伺服器的參數,多個參數之間用&隔開,比如
      http://www.test.com/login?username=123&pwd=234&type=JSON
    • 由於瀏覽器和伺服器對URL長度有限制,因此在URL後面附帶的參數是有限制的,通常不能超過1KB
  • POST
    • 發給伺服器的參數全部放在請求體中
    • 理論上,POST傳遞的數據量沒有限制(具體還得看伺服器的處理能力)
  • 如何選擇【除簡單數據查詢外,其它的一律使用POST請求】
  • a.如果要傳遞大量數據,比如文件上傳,只能用POST請求
  • b.GET的安全性比POST要差些,如果包含機密\敏感信息,建議用POST
  • c.如果僅僅是索取數據(數據查詢),建議使用GET
  • d.如果是增加、修改、刪除數據,建議使用POST

iOS中發送HTTP請求的方案

蘋果原生 特點
NSURLConnection 03年推出的古老技術
NSURLSession 13年推出iOS7之後,以取代NSURLConnection 【重點】
CFNetwork 底層技術、C語言的

常用第三方框架

第三方框架
ASIHttpRequest
AFNetworking 開發常用
MKNetworkKit

HTTP請求通信過程

  • 請求
  • 【包括請求頭+請求體·非必選】
  • 響應
  • 【響應頭+響應體】
  • 通信過程
  • a.發送請求的時候把請求頭和請求體(請求體是非必須的)包裝成一個請求對象
  • b.伺服器端對請求進行響應,在響應信息中包含響應頭和響應體,響應信息是對伺服器端的描述,具體的信息放在響應體中傳遞給客戶端
  • 狀態碼
  • 【200】:請求成功
  • 【400】:客戶端請求的語法錯誤,伺服器無法解析
  • 【404】:無法找到資源
  • 【500】:伺服器內部錯誤,無法完成請求

NSURLConnection使用


NSURLConnection同步請求(GET)

步驟

1 確定請求路徑
2 創建請求對象(預設是GET請求,且已經預設包含了請求頭)
3 使用NSURLSession sendsync方法發送網路請求
4 接收到伺服器的響應後,解析響應體

代碼


    // 1.確定路徑
    NSURL *url = [NSURL URLWithString:@"http://m.news.baidu.com/news?fr=mohome&ssid=0&from=1001703a&uid=&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&bd_page_type=1"];

    // 2.創建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    // 3.發送同步請求
    NSURLResponse *response = nil;
    NSError *error = nil;
    
    // sendSynchronousRequest阻塞式的方法,會卡住線程
    /*
     第一個參數:請求對象
     第二個參數:響應頭信息,當該方法執行完畢之後,該參數被賦值
     第三個參數:錯誤信息,如果請求失敗,則error有值
     */
    NSData *date = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    
    // 4.解析伺服器返回的數據
    NSString *string = [[NSString alloc] initWithData:date encoding:NSUTF8StringEncoding];

NSURLConnection非同步請求(GET-SendAsync)

說明

該方法不會卡住當前線程,網路請求任務是非同步執行的

代碼

    // 1.確定路徑
    NSURL *url = [NSURL URLWithString:@"http://m.news.baidu.com/news?fr=mohome&ssid=0&from=1001703a&uid=&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&bd_page_type=1"];

    // 2.創建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // 3.發送非同步請求
    /*
     第一個參數:請求對象
     第二個參數:回調方法在哪個線程中執行,如果是主隊列則block在主線程中執行,非主隊列則在子線程中執行
     第三個參數:completionHandlerBlock塊:接受到響應的時候執行該block中的代碼
        response:響應頭信息
        data:響應體
        connectionError:錯誤信息,如果請求失敗,那麼該參數有值
     */
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {

        // 4.解析伺服器返回的數據
        NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        // 轉換並列印響應頭信息
        NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
        NSLog(@"--%zd---%@--",r.statusCode,r.allHeaderFields);
    }];

NSURLConnection非同步請求(GET-代理)

步驟

1 確定請求路徑
2 創建請求對象
3 創建NSURLConnection對象並設置代理
4 遵守NSURLConnectionDataDelegate協議,並實現相應的代理方法
5 在代理方法中監聽網路請求的響應

設置代理的幾種方法


     /*
     設置代理的第一種方式:自動發送網路請求
     [[NSURLConnection alloc]initWithRequest:request delegate:self];
     */

    /*
     設置代理的第二種方式:
     第一個參數:請求對象
     第二個參數:誰成為NSURLConnetion對象的代理
     第三個參數:是否馬上發送網路請求,如果該值為YES則立刻發送,如果為NO則不會發送網路請求
     NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];

     //調用該方法控制網路請求的發送
     [conn start];
     */

    //設置代理的第三種方式:使用類方法設置代理,會自動發送網路請求
    NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
    //取消網路請求
    //[conn cancel];

相關的代理方法

/*
 1.當接收到伺服器響應的時候調用
 第一個參數connection:監聽的是哪個NSURLConnection對象
 第二個參數response:接收到的伺服器返回的響應頭信息
 */
- (void)connection:(nonnull NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response

/*
 2.當接收到數據的時候調用,該方法會被調用多次
 第一個參數connection:監聽的是哪個NSURLConnection對象
 第二個參數data:本次接收到的服務端返回的二進位數據(可能是片段)
 */
- (void)connection:(nonnull NSURLConnection *)connection didReceiveData:(nonnull NSData *)data
/*

 3.當服務端返回的數據接收完畢之後會調用
 通常在該方法中解析伺服器返回的數據
 */
-(void)connectionDidFinishLoading:(nonnull NSURLConnection *)connection

/*4.當請求錯誤的時候調用(比如請求超時)
 第一個參數connection:NSURLConnection對象
 第二個參數:網路請求的錯誤信息,如果請求失敗,則error有值
 */
- (void)connection:(nonnull NSURLConnection *)connection didFailWithError:(nonnull NSError *)error

其它

    01 關於消息彈窗第三方框架的使用
        SVProgressHUD
    02 字元串截取相關方法
    - (NSRange)rangeOfString:(NSString *)searchString;
    - (NSString *)substringWithRange:(NSRange)range;

NSURLConnection發送POST請求


步驟

a.確定URL路徑
b.創建請求對象(可變對象)
c.修改請求對象的方法為POST,設置請求體(Data)
d.發送一個非同步請求
e.補充:設置請求超時,處理錯誤信息,設置請求頭(如獲取客戶端的版本等等,請求頭是可設置可不設置的)

代碼

 //1.確定請求路徑
    NSURL *url = [NSURL URLWithString:@"http://m.news.baidu.com/news"];

    //2.創建請求對象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    //2.1更改請求方法
    request.HTTPMethod = @"POST";

    //2.2設置請求體
    request.HTTPBody = [@"fr=mohome&ssid=0&from=1001703a&uid=&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&bd_page_type=1" dataUsingEncoding:NSUTF8StringEncoding];

    //2.3請求超時
    request.timeoutInterval = 5;

    //2.4設置請求頭
    [request setValue:@"ios 9.0" forHTTPHeaderField:@"User-Agent"];


    //3.發送請求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {

        //4.解析伺服器返回的數據
        if (connectionError) {
            NSLog(@"--請求失敗-");
        }else
        {
            NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }

    }];

URL中文轉碼問題

   //1.確定請求路徑

    NSString *urlStr = @"http://m.news.baidu.com/news?fr=mohome&ssid=0&from=1001703a&uid=&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&bd_page_type=1";
    NSLog(@"%@",urlStr);
    //中文轉碼操作
    urlStr =  [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",urlStr);

    NSURL *url = [NSURL URLWithString:urlStr];

NSURLConnection


  • 兩種為NSURLConnection設置代理方式的區別

    //第一種設置方式:
    //通過該方法設置代理,會自動的發送請求
    // [[NSURLConnection alloc]initWithRequest:request delegate:self];

    //第二種設置方式:
    //設置代理,startImmediately為NO的時候,該方法不會自動發送請求
    NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
    //手動通過代碼的方式來發送請求
    //註意該方法內部會自動的把connect添加到當前線程的RunLoop中在預設模式下執行
    [connect start];
  • 如何控制代理方法在哪個線程調用

    //說明:預設情況下,代理方法會在主線程中進行調用(為了方便開發者拿到數據後處理一些刷新UI的操作不需要考慮到線程間通信)
    //設置代理方法的執行隊列
    [connect setDelegateQueue:[[NSOperationQueue alloc]init]];
  • 開子線程發送網路請求的註意點,適用於自動發送網路請求模式

//在子線程中發送網路請求-調用startf方法發送
-(void)createNewThreadSendConnect1
{
    //1.創建一個非主隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.封裝操作,並把任務添加到隊列中執行
    [queue addOperationWithBlock:^{

        NSLog(@"%@",[NSThread currentThread]);
        //2-1.確定請求路徑
        NSURL *url = [NSURL URLWithString:@"http://m.news.baidu.com/news?fr=mohome&ssid=0&from=1001703a&uid=&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&bd_page_type=1"];

        //2-2.創建請求對象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        //2-3.使用NSURLConnection設置代理,發送網路請求
        NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];

        //2-4.設置代理方法在哪個隊列中執行,如果是非主隊列,那麼代理方法將再子線程中執行
        [connection setDelegateQueue:[[NSOperationQueue alloc]init]];

        //2-5.發送網路請求
        //註意:start方法內部會把當前的connect對象作為一個source添加到當前線程對應的runloop中
        //區別在於,如果調用start方法開發送網路請求,那麼再添加source的過程中,如果當前runloop不存在
        //那麼該方法內部會自動創建一個當前線程對應的runloop,並啟動。
        [connection start];

    }];
}

//在子線程中發送網路請求-自動發送網路請求
-(void)createNewThreadSendConnect2
{
    NSLog(@"-----");
    //1.創建一個非主隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.封裝操作,並把任務添加到隊列中執行
    [queue addOperationWithBlock:^{

        //2-1.確定請求路徑
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=dd&pwd=ww&type=JSON"];

        //2-2.創建請求對象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        //2-3.使用NSURLConnection設置代理,發送網路請求
        //註意:該方法內部雖然會把connection添加到runloop,但是如果當前的runloop不存在,那麼不會主動創建。
        NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];

        //2-4.設置代理方法在哪個隊列中執行,如果是非主隊列,那麼代理方法將再子線程中執行
        [connection setDelegateQueue:[[NSOperationQueue alloc]init]];

        //2-5 創建當前線程對應的runloop,並開啟
       [[NSRunLoop currentRunLoop]run];
    }];
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 還記得之前的javascript入門裡的講的confirm 消息對話框嗎?不記得也沒關係,我們先來回顧一下,然後在詳細講它。 複習: confirm 消息對話框通常用於允許用戶做選擇的動作,如:“你對嗎?”等。彈出對話框(包括一個確定按鈕和一個取消按鈕)。 語法: 參數說明: str:在消息對話框中 ...
  • 當初始化SpaceShip原型時,我們尚未創建任何能作為第一個參數來傳遞的場景。並且SpaceShip的原型加入到場景的註冊表中,而這絕不是我們想做的。這是一種使用子類時常用的方法。應當僅僅在子類構造函數中調用父類構造函數,而不是當創建子類原型時調用它。 一旦創建了SpaceShip的原型對象,我們... ...
  • 當頁面使用 UITabBarController + UINavigationController 框架的時候,當跳轉到詳情頁面的時候,如果 UITabBar 仍然存在的話就會造成邏輯混亂,用戶體驗也會下降,因此我們就有一個在詳情頁將 UITabBar 隱藏的需求,當然,在其他的一些情況也可能有隱藏 ...
  • 用類對象作為ArrayAdapter綁定的基本數據類型(和SimpleAdater效果類似) 一般ArrayAdapter綁定的基本數據類型是String,接下來介紹一下類對象作為基本數據類型; 首先,新建一個類News,這個類作為基本的數據類型 接下來先把listView的item的佈局確定下來, ...
  • 最近因為項目需要對聲音進行變聲,所以邊學習邊做,發現音頻的處理思路並不難,但是做起來還是有些繁瑣的(比預期的) 趁著腦子還發熱,趕緊把思路總結一下,記錄下來。 主要講三個部分 1,如何變聲2,安卓實現變聲3,ios實現變聲 1. 要想自己寫一個變聲的函數或者庫出來,談何容易,所以採用了大家普遍採用的 ...
  • 從寫第一篇Swift文章的時候到現在Swift已經從1.2發展到了今天的3.0,這期間由於Swift目前還在發展階段並不能向下相容,因此第一篇文章中的部分代碼在當前的Xcode環境中已經無法運行。在WWDC16上Apple公佈了Swift3.0,從中可以看出Apple對Swift的重視,以及Swif... ...
  • 上篇文章講到《Android 簡訊的備份》,本文主要實現Android 簡訊的還原,即是將一條 佈局文件: 添加代碼: 添加許可權: 運行項目,搞定 ...
  • 7.SurfaceFlinger SurfaceFlinger在前面的篇幅了,多有涉及。 SurfaceFlinger是GUI刷新UI的核心,所以任何關於SurfaceFlinger的改進都會對android UI系統有重大影響。 SurfaceFlinger主要分為4個部分 1)黃油計劃 proj ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...