一、什么是HTTP協議 ?
HTTP
本質上是一種協議,全稱是Hypertext Transfer Protocol
,即超文本傳輸協議
。HTTP
是一個基于TCP/IP
通信協議來傳遞數據, 從名字上可以看出該協議用于規定客戶端與服務端之間的傳輸規則,所傳輸的內容不局限于文本(其實可以傳輸任意類型的數據)。
二、HTTP請求/響應報文
當我們往服務端發送一條HTTP請求時都發送了哪些東西過去呢?先看一個POST請求的示例圖:
以上示例圖中其實已經包含了一個HTTP請求所必備的幾大要素:
請求行、請求頭(headerField)、請求體(body);同理,響應也有狀態行、響應頭、實體內容。
下圖給出了請求報文的一般格式。
2.1 請求行
請求行包含請求方法(Method)、請求統一資源標識符(URI)、HTTP版本號
- 請求方法就是我們所熟悉的POST、GET、HEAD、PUT等
- URI就是URL中排除掉Host剩下的部分,也就是資源在服務器本地上的路徑
- HTTP版本號,目前主流的版本是1.1(1999年開始采用),最新的版本是2.0(2015年5月發布)。
2.2 請求頭
請求頭主要存放對客戶端想給服務端的附加信息下, 如下圖所示
HTTP請求在iOS中用NSURLRequest與NSMutableRequest表示;HTTP響應用NSHTTPURLResponse表示。
- Host: 目標服務器的網絡地址
- Accept: 讓服務端知道客戶端所能接收的數據類型,如text/html /
- Content-Type: body中的數據類型,如application/json; charset=UTF-8
- Accept-Language: 客戶端的語言環境,如zh-cn
- Accept-Encoding: 客戶端支持的數據壓縮格式,如gzip
- User-Agent: 客戶端的軟件環境,我們可以更改該字段為自己客戶端的名字,比如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才開始有的,用來告訴服務端這是一個持久連接,“請服務端不要在發出響應后立即斷開TCP連接”。關于該字段的更多解釋將在后面的HTTP版本簡介中展開。
- Content-Length: body的長度,如果body為空則該字段值為0。該字段一般在POST請求中才會有。
- Cookie: 記錄者用戶信息的保存在本地的用戶數據,如果有會被自動附上
值得一提的是,在iOS中當你發送一個任意請求時,不管你愿不愿意,NSURLRequest都會自動幫你記錄你所訪問的URL上設置的cookie。在iOS中用NSHTTPCookieStorage表示,是一個單例。通過
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
NSLog(@"%@", cookie);
}
以上就是我們日常開發中比較經常遇到的請求頭,其實還有其他的field。那在iOS中如何設置添加這些field呢?可以使用-[NSMutableURLRequest addValue: forHTTPHeaderField:]
方法,獲取當前請求已經設置的field可以用-[NSURLRequest allHTTPHeaderFields]
。也就是我們可以通過以上接口定制我們所需要的請求頭,但是有些field是不能改的
2.3、請求體
真正需要發給服務端的數據,在使用POST-multipart上傳請求中請求體就是上傳文件的二進制NSData類型數據;在GET請求中請求體為空;在普通的POST請求中請求體就是一些表單數據。在iOS中一般用NSURLRequest
與NSMutableURLRequest
的HTTPBody
屬性表示,添加body用-[NSMutableURLRequest setHTTPBody:]
。
2.4、響應行
狀態行是服務端返回給客戶端的狀態信息,包含HTTP版本號、狀態碼、狀態碼對應的英文名稱。
以下就是典型的正確狀態行:
HTTP/1.1 200 OK
這個部分需要講的是錯誤碼。事實上HTTP請求錯誤碼可以根據錯誤碼從左往右第一個數字大致分為以下幾類:
1XX:信息提示。不代表成功或者失敗,表示臨時響應,比如100表示繼續,101表示切換協議
2XX: 成功
3XX: 重定向
4XX:客戶端錯誤,很有可能是客戶端發生問題,如親切可愛的404
表示未找到文件,說明你的URI是有問題的,服務器機子上該目錄是沒有該文件的;414
URI太長
5XX: 服務器錯誤,比如504
網關超時
HTTP狀態碼詳細列表: http://www.runoob.com/http/http-status-codes.html
2.5、響應頭與響應實體
這部分與請求部分差異不大,響應頭的字field會有稍許不同,響應頭中的header field同樣移步請求頭響應頭列表。
三、HTTP版本簡介
這里我把HTTP版本簡單分為三類:1.1之前,1.1,2.0,針對這三類做個主要差異的介紹:
- HTTP 1.1之前
- 不支持持久連接。一旦服務器對客戶端發出響應就立即斷開TCP連接
- 無請求頭跟響應頭
- 客戶端的前后請求是同步的。下一個請求必須等上一個請求從服務端拿到響應后才能發出,有點類似多線程的同步機制。
- HTTP 1.1(主流版本)
- 與1.1之前的版本相比,做了以下性能上的提升
- 增加請求頭跟響應頭
- 支持持久連接。客戶端通過請求頭中指定Connection為keep-alive告知服務端不要在完成響應后立即釋放連接。HTTP是基于TCP的,在HTTP 1.1中一次TCP連接可以處理多次HTTP請求
- 客戶端不同請求之間是異步的。下一個請求不必等到上一個請求回來后再發出,而可以連續發出請求,有點類似多線程的異步處理。
- HTTP 2.0
- 本著向下兼容的原則,1.1版本有的特性2.0都具備,也使用相同的API。但是2.0將只用于https網址。由于2.0的普及還需要比較長的一段時間,這里不展開
我們重點關注一下當前1.1版本所做幾點改變。支持持久連接有什么好處呢?
HTTP是基于TCP連接的,如果連接被頻繁地啟動然后斷開就會花費很多資源在TCP三次握手以及四次揮手上,效率低下。以請求一個網頁為例,我們知道,一個html網頁上的圖片資源并不是直接嵌入在網頁上,而只是提供url,圖片仍需要額外發HTTP 請求去下載。一個網頁從請求到最終加載到本地往往需要經過過個HTTP請求。在1.1版本之前請求一個網頁就需要發生多次"握手-揮手"的過程,每次連接之間相互獨立;而1.1及之后的版本最少只需要一次就夠。
再來就是請求異步,其好處參考多線程異步處理,在此不展開。
以上特性可以用圖2.3表示:
我們可以看到:1、N次請求其實只建立了1次TCP連接,2、N次請求連續異步發出。
四 、HTTP協議特點
HTTP 是一個屬于應用層的面向對象的協議,HTTP 協議一共有五大特點:1、支持客戶/服務器模式;2、簡單快速;3、靈活;4、無連接;5、無狀態
。
- 支持客戶/服務器模式。
- 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與服務器聯系的類型不同。由于HTTP協議簡單,使得HTTP服務器的程序規模小,因而通信速度很快。
- 靈活:HTTP允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type(Content-Type是HTTP包中用來表示內容類型的標識)加以標記。
- 無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。
- 無狀態:HTTP協議是無狀態協議。無狀態是指協議對于事務處理沒有記憶能力。缺少狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。
五、HTTP建立過程
- 首先需要進行 Tcp 的三次握手
- HTTP 的請求/響應過程
- Tcp 四次揮手連接釋放
如下圖所示:
五、HTTP、Socket、TCP的區別
這三個概念經常被談到,也是比較容易被混掉的概念。在回顧之前我們先看一下這三者在TCP/IP協議族中的位置關系:
HTTP是應用層的協議,更靠近用戶端;TCP是傳輸層的協議;而socket是從傳輸層上抽象出來的一個抽象層,本質是接口。所以本質上三種還是很好區分的。盡管如此,有時候你可能會懵逼,HTTP連接、TCP連接、socket連接有什么區別?好吧,如果上面的圖解釋的還是不夠清楚的話,我們繼續往下看。
4.1 TCP連接與HTTP連接的區別
上文提過,HTTP是基于TCP的,客戶端往服務端發送一個HTTP請求時第一步就是要建立與服務端的TCP連接,也就是先三次握手,“你好,你好,你好”。從HTTP 1.1開始支持持久連接,也就是一次TCP連接可以發送多次的HTTP請求。
小總結:HTTP基于TCP
4.2、TCP連接與Socket連接的區別
在圖4.1中我們提到,socket層只是在TCP/UDP傳輸層上做的一個抽象接口層,因此一個socket連接可以基于TCP,也有可能基于UDP。基于TCP協議的socket連接同樣需要通過三次握手建立連接,是可靠的;基于UDP協議的socket連接不需要建立連接的過程,不過對方能不能收到都會發送過去,是不可靠的,大多數的即時通訊IM都是后者。
小總結:Socket也可以基于TCP
4.3、HTTP連接與Socket連接的區別
區分這兩個概念是比較有意義的,畢竟TCP看不見摸不著,HTTP與Socket是實實在在能用到的。
- HTTP是短連接,Socket(基于TCP協議的)是長連接。盡管HTTP1.1開始支持持久連接,但仍無法保證始終連接。而Socket連接一旦建立TCP三次握手,除非一方主動斷開,否則連接狀態一直保持。
- HTTP連接服務端無法主動發消息,Socket連接雙方請求的發送先后限制。這點就比較重要了,因為它將決定二者分別適合應用在什么場景下。HTTP采用“請求-響應”機制,在客戶端還沒發送消息給服務端前,服務端無法推送消息給客戶端。必須滿足客戶端發送消息在前,服務端回復在后。Socket連接雙方類似peer2peer的關系,一方隨時可以向另一方喊話。
4.4、問題來了:什么時候該用HTTP,什么時候該用socket
這個問題的提出是很自然而然的。當你接到一個與另一方的網絡通訊需求,自然會考慮用HTTP還是用Socket。
- 用HTTP的情況:雙方不需要時刻保持連接在線,比如客戶端資源的獲取、文件上傳等
- 用Socket的情況:大部分即時通訊應用(QQ、微信)、聊天室、蘋果APNs等
在iOS中,發HTTP請求一般用原生的NSURLConnection
、NSURLSession
或者開源的AFNetWorking(推薦)
、ASIHttpRequest(已停止更新)
。連接Socket連接我用的比較多是robbiehanson大神的[CocoaAsyncSocket] (XMPPFramework
也是出自他手)。
六. TCP/UDP
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)協議屬于傳輸層協議。其中TCP提供IP環境下的數據可靠傳輸,它提供的服務包括數據流傳送、可靠性、有效流控、全雙工操作和多路復用。通過面向連接、端到端和可靠的數據包發送。而UDP則不為IP提供可靠性、流控或差錯恢復功能。一般來說,TCP對應的是可靠性要求高的應用,而UDP對應的則是可靠性要求低、傳輸經濟的應用。
6.1 TCP
TCP(傳輸控制協議)
是基于連接的協議,是面向連接的, 也就是說,在正式收發數據前,必須和對方建立可靠的連接。一個TCP連接必須要經過三次“對話”才能建立起來經過三次“對話”之后,主機A才向主機B正式發送數據。
TCP協議能為應用程序提供可靠的通信連接,使一臺計算機發出的字節流無差錯地發往網絡上的其他計算機,對可靠性要求高的數據通信系統]往往使用TCP協議傳輸數據。
6.2 UDP
UDP(用戶數據報協議)
是與TCP相對應的協議。它是面向非連接
的協議,它不與對方建立連接,而是直接就把數據包
發送過去!UDP適用于一次只傳送少量數據、對可靠性要求不高的應用環境可以使用UDP
6.3 TCP/ UDP區別
- TCP面向連接(三次握手);UDP是無連接的,即發送數據之前不需要建立連接
- TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重復,且按序到達;UDP盡最大努力交付,即不保證可靠交付, Tcp通過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。如丟包時的重發控制,還可以對次序亂掉的分包進行順序控制。
- UDP具有較好的實時性,工作效率比TCP高,適用于對高速傳輸和實時性有較高的通信或廣播通信。
- 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
- TCP對系統資源要求較多,UDP對系統資源要求較少。
七. DNS
域名系統(DomainNameSystem,縮寫:DNS)是[互聯網]的一項服務。它作為將域名和IP地址相互映射的一個分布式數據庫,能夠使人更方便地訪問[互聯網], 工作原理如下圖:
DNS解析查詢方式
-
(1)遞歸查詢
遞歸查詢是一種DNS 服務器的查詢模式,在該模式下DNS 服務器接收到客戶機請求,必須使用一個準確的查詢結果回復客戶機。如果DNS 服務器本地沒有存儲查詢DNS 信息,那么本地服務器就會成為DNS中的一臺客戶機,并向上級域名服務器發出查詢請求,這種過程將持續到找到具有相關信息的域名服務器為止,然后將返回的查詢結果提交給客戶機。
過程中如果沒有找到查詢結果,重復遞歸上述操作直至根域名服務器,根域名服務器收到DNS請求后,把所查詢得到的所請求的DNS域名中發送給頂級域名服務器,讓頂級域名服務器去往下級域名服務器請求查找,如果找到了就原路返回。某域名服務器-->...->頂級域名服務器-->根域名服務器-->下一級域名服務器-->...-->本地域名服務器-->客戶機。如果沒有找到就報錯,表示無法查詢到相關信息;
image.png
-
(2)迭代查詢
DNS 服務器另外一種查詢方式為迭代查詢,DNS 服務器會向客戶機提供其他能夠解析查詢請求的DNS 服務器地址,當客戶機發送查詢請求時,DNS 服務器并不直接回復查詢結果,而是告訴客戶機另一臺DNS 服務器地址,客戶機再向這臺DNS 服務器提交請求,依次循環直到返回查詢的結果為止。
image.png
DNS劫持問題
DNS劫持又稱(域名劫持
), 是指在劫持的網絡范圍內攔截域名解析的請求,分析請求的域名,把審查范圍以外的請求放行,否則返回假的IP地址或者什么都不做使請求失去響應,其效果就是對特定的網絡不能訪問或訪問的是假網址。
DNS劫持問題解決方案:
-
HTTPDNS
HTTPDNS 利用 HTTP 協議與 DNS 服務器交互,代替了傳統的基于 UDP 協議的 DNS 交互,繞開了運營商的 Local DNS,有效防止了域名劫持,提高域名解析效率。
image.png
參考鏈接:
http://www.runoob.com/http/http-tutorial.html
https://www.cnblogs.com/xuxinstyle/p/9813654.html
https://blog.csdn.net/qq_34115899/article/details/82981007