簡單 -http詳解

HTTP屬于老話題了洒闸,在項目中我們經(jīng)常需要往服務(wù)端發(fā)POST或者GET請求蔑歌,但是對于HTTP的了解不應(yīng)只局限于此震叙。千里之行掀鹅,始于足下。越想走的遠媒楼,基本原理就應(yīng)該了解的透徹全面一些乐尊,僅僅停留在使用ASIHttpRequest或者AFNetWorking傳個參數(shù)發(fā)個請求的程度上是不夠的。這篇文章就是帶你全方面回顧一下HTTP匣砖。

通過本文你能收獲哪些內(nèi)容:

完整HTTP請求與響應(yīng)包含的必要元素

HTTP不同版本之間的差異

HTTP科吭、Socket、TCP的區(qū)別(易混)

一猴鲫、HTTP協(xié)議

HTTP本質(zhì)上是一種協(xié)議对人,全稱是Hypertext Transfer Protocol,即超文本傳輸協(xié)議拂共。從名字上可以看出該協(xié)議用于規(guī)定客戶端與服務(wù)端之間的傳輸規(guī)則牺弄,所傳輸?shù)膬?nèi)容不局限于文本(其實可以傳輸任意類型的數(shù)據(jù))。


二宜狐、HTTP請求與響應(yīng)的內(nèi)容

當我們往服務(wù)端發(fā)送一條HTTP請求時都發(fā)送了哪些東西過去呢势告?

先看一個POST請求的示例圖:


注:本文使用來模擬發(fā)送HTTP請求蛇捌,使用Charles抓包,Charles選中"Request"以及"Raw"選項就可以看到請求的全部內(nèi)容

以上示例圖中其實已經(jīng)包含了一個HTTP請求所必備的幾大要素:請求行咱台、請求頭(headerField)络拌、請求體(body);同理回溺,響應(yīng)也有狀態(tài)行春贸、響應(yīng)頭、實體內(nèi)容遗遵。接下來我們逐個展開萍恕。

1、請求行

請求行包含請求方法(Method)车要、請求統(tǒng)一資源標識符(URI)允粤、HTTP版本號,如圖2.1第一行所示:


請求方法就是我們所熟悉的POST翼岁、GET类垫、HEAD、PUT等

URI就是URL中排除掉Host剩下的部分登澜,也就是資源在服務(wù)器本地上的路徑

HTTP版本號阔挠,目前主流的版本是1.1(1999年開始采用),最新的版本是2.0(2015年5月發(fā)布)脑蠕。不同版本之間差異下面會再展開

2、請求頭

請求頭主要存放對客戶端想給服務(wù)端的附加信息跪削,下圖框框的部分就是請求頭:


HTTP請求在iOS中用NSURLRequest與NSMutableRequest表示谴仙;HTTP響應(yīng)用NSHTTPURLResponse表示。

Host: 目標服務(wù)器的網(wǎng)絡(luò)地址

Accept: 讓服務(wù)端知道客戶端所能接收的數(shù)據(jù)類型碾盐,如text/html */*

Content-Type: body中的數(shù)據(jù)類型晃跺,如application/json; charset=UTF-8

Accept-Language: 客戶端的語言環(huán)境,如zh-cn

Accept-Encoding: 客戶端支持的數(shù)據(jù)壓縮格式毫玖,如gzip

User-Agent: 客戶端的軟件環(huán)境掀虎,我們可以更改該字段為自己客戶端的名字,比如QQ music v1.11付枫,比如瀏覽器Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2

Connection: keep-alive烹玉,該字段是從HTTP 1.1才開始有的,用來告訴服務(wù)端這是一個持久連接阐滩,“請服務(wù)端不要在發(fā)出響應(yīng)后立即斷開TCP連接”二打。關(guān)于該字段的更多解釋將在后面的HTTP版本簡介中展開。

Content-Length: body的長度掂榔,如果body為空則該字段值為0继效。該字段一般在POST請求中才會有症杏。

POST請求的body請求體也有可能是空的,因此POST中Content-Length也有可能為0

Cookie: 記錄者用戶信息的保存在本地的用戶數(shù)據(jù)瑞信,如果有會被自動附上

值得一提的是厉颤,在iOS中當你發(fā)送一個任意請求時,不管你愿不愿意凡简,NSURLRequest都會自動幫你記錄你所訪問的URL上設(shè)置的cookie逼友。在iOS中用NSHTTPCookieStorage表示,是一個單例潘鲫。通過

NSHTTPCookieStorage?*cookieJar?=?[NSHTTPCookieStorage?sharedHTTPCookieStorage];

for(NSHTTPCookie?*cookiein[cookieJar?cookies])?{

NSLog(@"%@",?cookie);

}

可以獲取目前被自動保存的所有cookie翁逞。對cookie的操作感興趣的請移步iOS中http請求使用cookie這篇文章。

以上就是我們?nèi)粘i_發(fā)中比較經(jīng)常遇到的請求頭溉仑,其實還有其他的field挖函,但篇幅所限無法一一列出,想了解所有請求頭請看這里請求頭響應(yīng)頭列表浊竟。那在iOS中如何設(shè)置添加這些field呢怨喘?可以使用-[NSMutableURLRequest addValue: forHTTPHeaderField:]方法,獲取當前請求已經(jīng)設(shè)置的field可以用-[NSURLRequest allHTTPHeaderFields]振定。也就是我們可以通過以上接口定制我們所需要的請求頭必怜,但是有些field是不能改的,我們看一下iOS的描述:


從文檔中我們可以看到后频,在iOS中不應(yīng)當對Authorization Connection Host WWW-Authenticate這幾個header field做更改梳庆。

3、請求體

真正需要發(fā)給服務(wù)端的數(shù)據(jù)卑惜,在使用POST-multipart上傳請求中請求體就是上傳文件的二進制NSData類型數(shù)據(jù)膏执;在GET請求中請求體為空;在普通的POST請求中請求體就是一些表單數(shù)據(jù)露久。在iOS中一般用NSURLRequest與NSMutableURLRequest的HTTPBody屬性表示更米,添加body用-[NSMutableURLRequest setHTTPBody:]。

4毫痕、響應(yīng)狀態(tài)行

狀態(tài)行是服務(wù)端返回給客戶端的狀態(tài)信息征峦,包含HTTP版本號、狀態(tài)碼消请、狀態(tài)碼對應(yīng)的英文名稱栏笆。

以下就是典型的正確狀態(tài)行:

HTTP/1.1?200?OK

這個部分需要講的是錯誤碼。事實上HTTP請求錯誤碼可以根據(jù)錯誤碼從左往右第一個數(shù)字大致分為以下幾類:

1XX:信息提示梯啤。不代表成功或者失敗竖伯,表示臨時響應(yīng),比如100表示繼續(xù),101表示切換協(xié)議

2XX: 成功

3XX: 重定向

4XX:客戶端錯誤七婴,很有可能是客戶端發(fā)生問題祟偷,如親切可愛的404表示未找到文件,說明你的URI是有問題的打厘,服務(wù)器機子上該目錄是沒有該文件的修肠;414URI太長

5XX: 服務(wù)器錯誤,比如504網(wǎng)關(guān)超時

錯誤碼是不用去記的户盯,出錯了再查對應(yīng)的錯誤碼含義就行嵌施。但是知道上面的分類有助于第一時間做出大體的判斷,起碼你能清楚是服務(wù)端還是客戶端的原因莽鸭。

5吗伤、響應(yīng)頭與響應(yīng)實體

這部分與請求部分差異不大,響應(yīng)頭的字field會有稍許不同硫眨,響應(yīng)頭中的header field同樣移步請求頭響應(yīng)頭列表足淆。

三、HTTP版本簡介

這里我把HTTP版本簡單分為三類:1.1之前礁阁,1.1巧号,2.0,針對這三類做個主要差異的介紹:

HTTP 1.1之前

不支持持久連接姥闭。一旦服務(wù)器對客戶端發(fā)出響應(yīng)就立即斷開TCP連接

無請求頭跟響應(yīng)頭

客戶端的前后請求是同步的丹鸿。下一個請求必須等上一個請求從服務(wù)端拿到響應(yīng)后才能發(fā)出,有點類似多線程的同步機制棚品。

HTTP 1.1(主流版本)

與1.1之前的版本相比靠欢,做了以下性能上的提升

增加請求頭跟響應(yīng)頭

支持持久連接⊥埽客戶端通過請求頭中指定Connection為keep-alive告知服務(wù)端不要在完成響應(yīng)后立即釋放連接掺涛。HTTP是基于TCP的,在HTTP 1.1中一次TCP連接可以處理多次HTTP請求

客戶端不同請求之間是異步的疼进。下一個請求不必等到上一個請求回來后再發(fā)出,而可以連續(xù)發(fā)出請求秧廉,有點類似多線程的異步處理伞广。

HTTP 2.0

本著向下兼容的原則,1.1版本有的特性2.0都具備疼电,也使用相同的API嚼锄。但是2.0將只用于https網(wǎng)址。由于2.0的普及還需要比較長的一段時間蔽豺,這里不展開区丑,更多新特性請參考這篇文章

我們重點關(guān)注一下當前1.1版本所做幾點改變。支持持久連接有什么好處呢沧侥?HTTP是基于TCP連接的可霎,如果連接被頻繁地啟動然后斷開就會花費很多資源在TCP三次握手以及四次揮手上,效率低下宴杀。以請求一個網(wǎng)頁為例癣朗,我們知道,一個html網(wǎng)頁上的圖片資源并不是直接嵌入在網(wǎng)頁上旺罢,而只是提供url旷余,圖片仍需要額外發(fā)HTTP 請求去下載。一個網(wǎng)頁從請求到最終加載到本地往往需要經(jīng)過過個HTTP請求扁达。在1.1版本之前請求一個網(wǎng)頁就需要發(fā)生多次"握手-揮手"的過程正卧,每次連接之間相互獨立;而1.1及之后的版本最少只需要一次就夠跪解。

再來就是請求異步炉旷,其好處參考多線程異步處理,在此不展開惠遏。


我們可以看到:1砾跃、N次請求其實只建立了1次TCP連接,2节吮、N次請求連續(xù)異步發(fā)出抽高。

四、HTTP透绩、Socket翘骂、TCP的區(qū)別

這三個概念經(jīng)常被談到,也是比較容易被混掉的概念帚豪。在回顧之前我們先看一下這三者在TCP/IP協(xié)議族中的位置關(guān)系:


HTTP是應(yīng)用層的協(xié)議碳竟,更靠近用戶端;TCP是傳輸層的協(xié)議狸臣;而socket是從傳輸層上抽象出來的一個抽象層莹桅,本質(zhì)是接口。所以本質(zhì)上三種還是很好區(qū)分的烛亦。盡管如此诈泼,有時候你可能會懵逼,HTTP連接煤禽、TCP連接铐达、socket連接有什么區(qū)別?好吧檬果,如果上面的圖解釋的還是不夠清楚的話瓮孙,我們繼續(xù)往下看唐断。

1、TCP連接與HTTP連接的區(qū)別

上文提過杭抠,HTTP是基于TCP的脸甘,客戶端往服務(wù)端發(fā)送一個HTTP請求時第一步就是要建立與服務(wù)端的TCP連接,也就是先三次握手祈争,“你好斤程,你好,你好”菩混。從HTTP 1.1開始支持持久連接忿墅,也就是一次TCP連接可以發(fā)送多次的HTTP請求。

小總結(jié):HTTP基于TCP

2沮峡、TCP連接與Socket連接的區(qū)別

在圖4.1中我們提到疚脐,socket層只是在TCP/UDP傳輸層上做的一個抽象接口層,因此一個socket連接可以基于連接邢疙,也有可能基于UDP棍弄。基于TCP協(xié)議的socket連接同樣需要通過三次握手建立連接疟游,是可靠的呼畸;基于UDP協(xié)議的socket連接不需要建立連接的過程,不過對方能不能收到都會發(fā)送過去颁虐,是不可靠的蛮原,大多數(shù)的即時通訊IM都是后者。

小總結(jié):Socket也基于TCP

3另绩、HTTP連接與Socket連接的區(qū)別

區(qū)分這兩個概念是比較有意義的儒陨,畢竟TCP看不見摸不著,HTTP與Socket是實實在在能用到的笋籽。

HTTP是短連接蹦漠,Socket(基于TCP協(xié)議的)是長連接。盡管HTTP1.1開始支持持久連接车海,但仍無法保證始終連接笛园。而Socket連接一旦建立TCP三次握手,除非一方主動斷開侍芝,否則連接狀態(tài)一直保持喘沿。

HTTP連接服務(wù)端無法主動發(fā)消息,Socket連接雙方請求的發(fā)送先后限制竭贩。這點就比較重要了,因為它將決定二者分別適合應(yīng)用在什么場景下莺禁。HTTP采用“請求-響應(yīng)”機制留量,在客戶端還沒發(fā)送消息給服務(wù)端前,服務(wù)端無法推送消息給客戶端。必須滿足客戶端發(fā)送消息在前楼熄,服務(wù)端回復在后忆绰。Socket連接雙方類似peer2peer的關(guān)系,一方隨時可以向另一方喊話可岂。

4错敢、問題來了:什么時候該用HTTP,什么時候該用socket

這個問題的提出是很自然而然的缕粹。當你接到一個與另一方的網(wǎng)絡(luò)通訊需求稚茅,自然會考慮用HTTP還是用Socket。

用HTTP的情況:雙方不需要時刻保持連接在線平斩,比如客戶端資源的獲取亚享、文件上傳等。

用Socket的情況:大部分即時通訊應(yīng)用(QQ绘面、微信)欺税、聊天室、蘋果APNs等

在iOS中揭璃,發(fā)HTTP請求一般用原生的NSURLConnection晚凿、NSURLSession或者開源的AFNetWorking(推薦)、ASIHttpRequest(已停止更新)瘦馍。連接Socket連接我用的比較多是robbiehanson大神的CocoaAsyncSocket(XMPPFramework也是出自他手)歼秽。

五、The end

以上就是關(guān)于HTTP相關(guān)概念的回顧扣墩,適合菜鳥也適合有經(jīng)驗同學一起回顧哲银。

歡迎留言,如果寫的不對的地方還請不吝指出呻惕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荆责,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子亚脆,更是在濱河造成了極大的恐慌做院,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件濒持,死亡現(xiàn)場離奇詭異键耕,居然都是意外死亡,警方通過查閱死者的電腦和手機柑营,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門屈雄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人官套,你說我怎么就攤上這事酒奶∫峡祝” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵惋嚎,是天一觀的道長杠氢。 經(jīng)常有香客問我,道長另伍,這世上最難降的妖魔是什么鼻百? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮摆尝,結(jié)果婚禮上温艇,老公的妹妹穿的比我還像新娘。我一直安慰自己结榄,他們只是感情好中贝,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著臼朗,像睡著了一般邻寿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上视哑,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天绣否,我揣著相機與錄音,去河邊找鬼挡毅。 笑死蒜撮,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的跪呈。 我是一名探鬼主播段磨,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼耗绿!你這毒婦竟也來了苹支?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤误阻,失蹤者是張志新(化名)和其女友劉穎债蜜,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體究反,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡寻定,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了精耐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狼速。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖卦停,靈堂內(nèi)的尸體忽然破棺而出唐含,到底是詐尸還是另有隱情浅浮,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布捷枯,位于F島的核電站,受9級特大地震影響专执,放射性物質(zhì)發(fā)生泄漏淮捆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一本股、第九天 我趴在偏房一處隱蔽的房頂上張望攀痊。 院中可真熱鬧,春花似錦拄显、人聲如沸苟径。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棘街。三九已至,卻和暖如春承边,著一層夾襖步出監(jiān)牢的瞬間遭殉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工博助, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留险污,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓富岳,卻偏偏與公主長得像蛔糯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子窖式,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容