淺談網絡基礎,那些在開發中要用到的知識。

網絡在開發中無處不在,網絡方面的知識又比較雜,下面分享一下關于網絡的一些基礎知識,幫助大家快速了解一些知識.鞏固基礎,做到舉一反三,日進漸進.

如果你已經掌握了基礎內容,可以閱讀我的另一篇文章《關于AFNetworking,初級程序員到高級工程師的修煉之路》

1 網絡基礎
1)問題:為什么要學習網絡編程?
(1)網絡編程是一種實時更新應用數據的常用手段
(2)網絡編程是開發優秀網絡應用的前提和基礎

2)網絡基本概念
    (1)客戶端(就是手機或者ipad等手持設備上面的APP)
    (2)服務器(遠程服務器-本地服務器)
    (3)請求(客戶端索要數據的方式)
    (4)響應(需要客戶端解析數據)
    (5)數據庫(服務器的數據從哪里來)

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

2)http協議
    (1)http協議簡單介紹
         a.超文本傳輸協議
         b.規定客戶端和服務器之間的數據傳輸格式
         c.讓客戶端和服務器能有效地進行數據溝通
    (2)http協議優缺點
        a.簡單快速(協議簡單,服務器端程序規模小,通信速度快)
        b.靈活(允許傳輸各種數據)
        c.非持續性連接(1.1之前版本是非持續的,即限制每次連接只處理一個請求,服務器對客戶端的請求做出響應后,馬上斷開連接,這種方式可以節省傳輸時間)
    (3)基本通信過程
        a.請求:客戶端向服務器索要數據
        b.響應:服務器返回客戶端相應的數據

3) GET和POST請求
    (1)http里面發送請求的方法
            GET(常用)、POST(常用)、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
    (2)GET和POST請求的對比【區別在于參數如何傳遞】
            GET
            在請求URL后面以?的形式跟上發給服務器的參數,多個參數之間用&隔開,比如
            http://ww.GF.com/login?username=GF&pwd=GF&type=JSON
            由于瀏覽器和服務器對URL長度有限制,因此在URL后面附帶的參數是有限制的,通常不能超過1KB

            POST
            發給服務器的參數全部放在請求體中
            理論上,POST傳遞的數據量沒有限制(具體還得看服務器的處理能力)
    (3)如何選擇【除簡單數據查詢外,其它的一律使用POST請求】
            a.如果要傳遞大量數據,比如文件上傳,只能用POST請求
            b.GET的安全性比POST要差些,如果包含機密\敏感信息,建議用POST
            c.如果僅僅是索取數據(數據查詢),建議使用GET
            d.如果是增加、修改、刪除數據,建議使用POST

4)iOS中發送http請求的方案
    (1)蘋果原生
        NSURLConnection 03年推出的古老技術
        NSURLSession     13年推出iOS7之后,以取代NSURLConnection【重點】
        CFNetwork        底層技術、C語言的
    (2)第三方框架
        ASIHttpRequest
        AFNetworking         【重點】
        MKNetworkKit

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

2 NSURLConnection的基本使用

1 NSURLConnection同步請求(GET)
1)發送網絡請求的步驟
(1)設置請求路徑
(2)創建請求對象(默認是GET請求,且已經默認包含了請求頭)
(3)使用NSURLSession sendsync方法發送網絡請求
(4)接收到服務器的響應后,解析響應體

2)相關代碼
    //1.確定請求路徑
    NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/login?username=GF&pwd=GF&type=XML"];
    //NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/video?type=XML"];

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

    //3.把請求發送給服務器
    //sendSynchronousRequest  阻塞式的方法,會卡住線程

    NSHTTPURLResponse *response = nil;
    NSError *error = nil;

    /*
    第一個參數:請求對象
    第二個參數:響應頭信息,當該方法執行完畢之后,該參數被賦值
    第三個參數:錯誤信息,如果請求失敗,則error有值
    */
    //該方法是阻塞式的,會卡住線程
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    //4.解析服務器返回的數據
    NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

2 NSURLConnection異步請求(GET-SendAsync)
1)相關說明
01 該方法不會卡住當前線程,網絡請求任務是異步執行的

2)相關代碼
    //1.確定請求路徑
    NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/login?username=GF&pwd=GF"];

    //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);
    }];

3 NSURLConnection異步請求(GET-代理)
1)步驟
(1)確定請求路徑
(2)創建請求對象
(3)創建NSURLConnection對象并設置代理
(4)遵守NSURLConnectionDataDelegate協議,并實現相應的代理方法
(5)在代理方法中監聽網絡請求的響應

2)設置代理的幾種方法
    /*
     設置代理的第一種方式:自動發送網絡請求
     [[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];

3)相關的代理方法
    /*
     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

4)其它知識點
    01 關于消息彈窗第三方框架的使用
        SVProgressHUD
    02 字符串截取相關方法
    - (NSRange)rangeOfString:(NSString *)searchString;
    - (NSString *)substringWithRange:(NSRange)range;

4 NSURLConnection發送POST請求
1)發送POST請求步驟
a.確定URL路徑
b.創建請求對象(可變對象)
c.修改請求對象的方法為POST,設置請求體(Data)
d.發送一個異步請求
e.補充:設置請求超時,處理錯誤信息,設置請求頭(如獲取客戶端的版本等等,請求頭是可設置可不設置的)
2)相關代碼
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/login"];

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

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

    //2.2設置請求體
    request.HTTPBody = [@"username=GF&pwd=GF" dataUsingEncoding:NSUTF8StringEncoding];

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

    //2.4設置請求頭
    [request setValue:@"iOS9.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]);
        }
    }];

5 URL中文轉碼問題

//1.確定請求路徑
NSString *urlStr = @"http://114.114.114.114:32812/login2?username=GF&pwd=GF";
NSLog(@"%@",urlStr);
//中文轉碼操作
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",urlStr);

NSURL *url = [NSURL URLWithString:urlStr];

3 NSURLConnection和Runloop(面試)

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

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

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

2 如何控制代理方法在哪個線程調用

//說明:默認情況下,代理方法會在主線程中進行調用(為了方便開發者拿到數據后處理一些刷新UI的操作不需要考慮到線程間通信)
//設置代理方法的執行隊列
[connect setDelegateQueue:[[NSOperationQueue alloc]init]];

3 開子線程發送網絡請求的注意點,適用于自動發送網絡請求模式

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

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

        NSLog(@"%@",[NSThread currentThread]);
        //2-1.確定請求路徑
        NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/login?username=dd&pwd=ww&type=JSON"];

        //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://114.114.114.114:32812/login?username=GF&pwd=GF&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];
    }];
}

4 NSURLSession的基本使用

1 NSURLSession的基本使用
1)使用步驟
使用NSURLSession創建task,然后執行task

2)關于task
    a.NSURLSessionTask是一個抽象類,本身不能使用,只能使用它的子類
    b.NSURLSessionDataTask\NSURLSessionUploadTask\NSURLSessionDownloadTask

3)發送get請求
    //1.創建NSURLSession對象(可以獲取單例對象)
    NSURLSession *session = [NSURLSession sharedSession];

    //2.根據NSURLSession對象創建一個Task

    NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/login?username=GF&pwd=GF&type=JSON"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    //方法參數說明
    /*
    注意:該block是在子線程中調用的,如果拿到數據之后要做一些UI刷新操作,那么需要回到主線程刷新
    第一個參數:需要發送的請求對象
    block:當請求結束拿到服務器響應的數據時調用block
    block-NSData:該請求的響應體
    block-NSURLResponse:存放本次請求的響應信息,響應頭,真實類型為NSHTTPURLResponse
    block-NSErroe:請求錯誤信息
     */
   NSURLSessionDataTask * dataTask =  [session dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {

        //拿到響應頭信息
        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

        //4.解析拿到的響應數據
        NSLog(@"%@\n%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],res.allHeaderFields);
    }];

    //3.執行Task
    //注意:剛創建出來的task默認是掛起狀態的,需要調用該方法來啟動任務(執行任務)
    [dataTask resume];

4)發送get請求的第二種方式

  //注意:該方法內部默認會把URL對象包裝成一個NSURLRequest對象(默認是GET請求)
    //方法參數說明
    /*
    //第一個參數:發送請求的URL地址
    //block:當請求結束拿到服務器響應的數據時調用block
    //block-NSData:該請求的響應體
    //block-NSURLResponse:存放本次請求的響應信息,響應頭,真實類型為NSHTTPURLResponse
    //block-NSErroe:請求錯誤信息
     */
- (nullable NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error))completionHandler;

5)發送POST請求
    //1.創建NSURLSession對象(可以獲取單例對象)
    NSURLSession *session = [NSURLSession sharedSession];

    //2.根據NSURLSession對象創建一個Task

    NSURL *url = [NSURL URLWithString:@"http://114.114.114.114:32812/login"];

    //創建一個請求對象,并這是請求方法為POST,把參數放在請求體中傳遞
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
        //拿到響應頭信息
        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

        //解析拿到的響應數據
        NSLog(@"%@\n%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],res.allHeaderFields);
    }];

    //3.執行Task
    //注意:剛創建出來的task默認是掛起狀態的,需要調用該方法來啟動任務(執行任務)
    [dataTask resume];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容