大部分的iOS開(kāi)發(fā)在剛開(kāi)始接觸網(wǎng)絡(luò)請(qǐng)求時(shí),應(yīng)該都是用的AFNetworking這個(gè)在iOS界扛把子的框架來(lái)做的吧极舔,但你們知道這個(gè)框架在做網(wǎng)絡(luò)請(qǐng)求的時(shí)候都做了什么嗎偷线。這篇文章會(huì)從系統(tǒng)原生的網(wǎng)絡(luò)請(qǐng)求來(lái)揭示網(wǎng)絡(luò)請(qǐng)求的本質(zhì)幔嗦,以后如果有時(shí)間會(huì)簡(jiǎn)單解析AFNetworking的源碼谒养。
原生網(wǎng)絡(luò)請(qǐng)求分為三個(gè)部分:
- NSMutableURLRequest請(qǐng)求類
先來(lái)一張網(wǎng)絡(luò)請(qǐng)求的抓包信息圖:
圖片來(lái)自:編程小翁
上圖便是一個(gè)完整的網(wǎng)絡(luò)請(qǐng)求的抓包示意圖,NSMutableURLRequest這個(gè)類就是管理者上半部分的所有信息身隐,如下圖框出來(lái)的部分:
圖片來(lái)自:編程小翁
其實(shí)就是網(wǎng)絡(luò)請(qǐng)求中的HTTPHeaderField信息廷区。我們來(lái)一一細(xì)說(shuō)其中作用(其中著重看Content-Type、Cookie贾铝、Content-Length隙轻,因?yàn)槲覀兣渲眠@些就行了埠帕。另外還有一個(gè)重要字段圖中沒(méi)有,那就是傳輸?shù)膬?nèi)容HTTPBody
代碼中會(huì)講到)玖绿。
POST:這個(gè)可以是GET或者別的請(qǐng)求方式敛瓷,這里放的是URL后半段
Host:這里是主機(jī)地址,Host和POST字段拼接起來(lái)就是一個(gè)完整的URL
Accept:這個(gè)網(wǎng)絡(luò)請(qǐng)求發(fā)送的數(shù)據(jù)的格式說(shuō)明:如Accept:text/html斑匪,這說(shuō)明這個(gè)網(wǎng)絡(luò)請(qǐng)求發(fā)送的
是HTML格式的數(shù)據(jù)呐籽。圖中的Accept:*/* 為通用格式。
Content-Type:這個(gè)字段表明數(shù)據(jù)發(fā)送方(也就是我們客戶端)想要接收的數(shù)據(jù)格式蚀瘸,一下有一個(gè)格式
對(duì)照表的截圖狡蝶。
Connection:網(wǎng)絡(luò)請(qǐng)求連接的方式,這個(gè)我們不用設(shè)置贮勃。
Cookie:我們只能從服務(wù)器得到這個(gè)字段贪惹,用于維持服務(wù)端會(huì)話狀態(tài),也可以用來(lái)做接口驗(yàn)證寂嘉,類似
token這樣的奏瞬。并且在iOS中,如果請(qǐng)求中cookie字段有值泉孩,蘋(píng)果會(huì)自動(dòng)幫我們保存下來(lái)丝格,
代碼中會(huì)講。
Accept-Language:表明可以接收什么文字棵譬,zh-cn表示中文。
Content-Length:表示傳輸內(nèi)容的長(zhǎng)度预伺。
Accept-Encoding:表示客戶端支持的編碼格式订咸,這個(gè)不用我們配置。
User-Agent:這個(gè)就像是一個(gè)網(wǎng)名酬诀,隨便寫(xiě)都可以脏嚷,一般不做配置。
創(chuàng)建一個(gè)NSMutableURLRequest
/** 創(chuàng)建request對(duì)象 */
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
/** 這個(gè)操作就是檢測(cè)cookie的方法瞒御,我們的系統(tǒng)會(huì)自動(dòng)將cookie保存下來(lái)父叙,通過(guò)下面的方法可以檢測(cè)出來(lái),如果服務(wù)器要求我們同步cookie肴裙,則在request中設(shè)置Cookie的值 */
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
if (cookie != nil) {
NSDictionary *headers=[NSHTTPCookie requestHeaderFieldsWithCookies:[cookieJar cookies]];
[request setValue:[headers objectForKey:@"Cookie"] forHTTPHeaderField:@"Cookie"];
}
}
/**
如果傳入?yún)?shù)不為空趾唱,則為POST請(qǐng)求
如果傳入的參數(shù)為nil,則為GET請(qǐng)求
*/
if (parameters != nil && parameters.count > 0) {
/** 傳入的參數(shù)為一個(gè)字典蜻懦,我們需要把字典轉(zhuǎn)化為一個(gè)以"&"分隔的字符串甜癞,再將字符串轉(zhuǎn)化為data,最后設(shè)置到HTTPBody里面去 */
NSData *bodyData = [self getDataFromParameters:parameters];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:bodyData];
[request setValue:[NSString stringWithFormat:@"%lld",(long long)bodyData.length] forHTTPHeaderField:@"Content-Length"];
/** 這個(gè)可以固定 */
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}
/** 設(shè)置請(qǐng)求時(shí)間 */
request.timeoutInterval = 8.0;
- NSURLSession會(huì)話類
- NSURLSessionDataTask會(huì)話任務(wù)類
把這兩個(gè)放到一起講宛乃,是因?yàn)檫@兩個(gè)很簡(jiǎn)單悠咱。一個(gè)request請(qǐng)求需要一個(gè)會(huì)話來(lái)啟動(dòng)和管理蒸辆,但我們僅僅只需要一個(gè)創(chuàng)建一個(gè)對(duì)象就行了
/** 創(chuàng)建會(huì)話對(duì)象 */
NSURLSession *session = [NSURLSession sharedSession];
最后我們需要把會(huì)話對(duì)象用來(lái)創(chuàng)建一個(gè)任務(wù)對(duì)象就完成了:
/** 創(chuàng)建會(huì)話任務(wù),并用會(huì)話對(duì)象啟動(dòng)請(qǐng)求對(duì)象 */
NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
注意一點(diǎn):會(huì)話任務(wù)需要手動(dòng)啟動(dòng)
/** 開(kāi)始任務(wù) */
[sessionDataTask resume];
至此析既,系統(tǒng)原生的網(wǎng)絡(luò)請(qǐng)求就完成了躬贡。
demo地址