UDP
面向報文
UDP 是一個面向報文(報文可以理解為一段段的數(shù)據(jù))的協(xié)議金抡。意思就是 UDP 只是報文的搬運工吟温,不會對報文進(jìn)行任何拆分和拼接操作。
具體來說
- 在發(fā)送端槽唾,應(yīng)用層將數(shù)據(jù)傳遞給傳輸層的 UDP 協(xié)議,UDP 只會給數(shù)據(jù)增加一個 UDP 頭標(biāo)識下是 UDP 協(xié)議光涂,然后就傳遞給網(wǎng)絡(luò)層了
- 在接收端庞萍,網(wǎng)絡(luò)層將數(shù)據(jù)傳遞給傳輸層,UDP 只去除 IP 報文頭就傳遞給應(yīng)用層忘闻,不會任何拼接操作
不可靠性
- UDP 是無連接的钝计,也就是說通信不需要建立和斷開連接。
- UDP 也是不可靠的。協(xié)議收到什么數(shù)據(jù)就傳遞什么數(shù)據(jù)私恬,并且也不會備份數(shù)據(jù)交播,對方能不能收到是不關(guān)心的
- UDP 沒有擁塞控制,一直會以恒定的速度發(fā)送數(shù)據(jù)践付。即使網(wǎng)絡(luò)條件不好永高,也不會對發(fā)送速率進(jìn)行調(diào)整命爬。這樣實現(xiàn)的弊端就是在網(wǎng)絡(luò)條件不好的情況下可能會導(dǎo)致丟包饲宛,但是優(yōu)點也很明顯,在某些實時性要求高的場景(比如電話會議)就需要使用 UDP 而不是 TCP家淤。
高效
因為 UDP 沒有 TCP 那么復(fù)雜絮重,需要保證數(shù)據(jù)不丟失且有序到達(dá)青伤。所以 UDP 的頭部開銷小狠角,只有八字節(jié)擎厢,相比 TCP 的至少二十字節(jié)要少得多动遭,在傳輸數(shù)據(jù)報文時是很高效的厘惦。
頭部包含了以下幾個數(shù)據(jù)
- 兩個十六位的端口號酝静,分別為源端口(可選字段)和目標(biāo)端口
- 整個數(shù)據(jù)報文的長度
- 整個數(shù)據(jù)報文的檢驗和(IPv4 可選 字段)别智,該字段用于發(fā)現(xiàn)頭部信息和數(shù)據(jù)中的錯誤
傳輸方式
UDP 不止支持一對一的傳輸方式薄榛,同樣支持一對多敞恋,多對多硬猫,多對一的方式啸蜜,也就是說 UDP 提供了單播盔性,多播,廣播的功能悉尾。
TCP
頭部
TCP 頭部比 UDP 頭部復(fù)雜的多
對于 TCP 頭部來說构眯,以下幾個字段是很重要的
- Sequence number,這個序號保證了 TCP 傳輸?shù)膱笪亩际怯行虻囊嫉辏瑢Χ丝梢酝ㄟ^序號順序的拼接報文
- Acknowledgement Number硅卢,這個序號表示數(shù)據(jù)接收端期望接收的下一個字節(jié)的編號是多少脉顿,同時也表示上一個序號的數(shù)據(jù)已經(jīng)收到
- Window Size艾疟,窗口大小汉柒,表示還能接收多少字節(jié)的數(shù)據(jù),用于流量控制
- 標(biāo)識符
- URG=1:該字段為一表示本數(shù)據(jù)報的數(shù)據(jù)部分包含緊急信息,是一個高優(yōu)先級數(shù)據(jù)報文恤溶,此時緊急指針有效咒程。緊急數(shù)據(jù)一定位于當(dāng)前數(shù)據(jù)包數(shù)據(jù)部分的最前面,緊急指針標(biāo)明了緊急數(shù)據(jù)的尾部饥瓷。
- ACK=1:該字段為一表示確認(rèn)號字段有效。此外棺克,TCP 還規(guī)定在連接建立后傳送的所有報文段都必須把 ACK 置為一。
- PSH=1:該字段為一表示接收端應(yīng)該立即將數(shù)據(jù) push 給應(yīng)用層因俐,而不是等到緩沖區(qū)滿后再提交撑帖。
- RST=1:該字段為一表示當(dāng)前 TCP 連接出現(xiàn)嚴(yán)重問題胡嘿,可能需要重新建立 TCP 連接,也可以用于拒絕非法的報文段和拒絕連接請求。
- SYN=1:當(dāng)SYN=1面氓,ACK=0時蛆橡,表示當(dāng)前報文段是一個連接請求報文呻拌。當(dāng)SYN=1,ACK=1時趾娃,表示當(dāng)前報文段是一個同意建立連接的應(yīng)答報文。
- FIN=1:該字段為一表示此報文段是一個釋放連接的請求報文。
狀態(tài)機(jī)
HTTP 是無連接的,所以作為下層的 TCP 協(xié)議也是無連接的培遵,雖然看似 TCP 將兩端連接了起來,但是其實只是兩端共同維護(hù)了一個狀態(tài)
TCP 的狀態(tài)機(jī)是很復(fù)雜的,并且與建立斷開連接時的握手息息相關(guān),接下來就來詳細(xì)描述下兩種握手。
在這之前需要了解一個重要的性能指標(biāo) RTT郎楼。該指標(biāo)表示發(fā)送端發(fā)送數(shù)據(jù)到接收到對端數(shù)據(jù)所需的往返時間。
建立連接三次握手
在 TCP 協(xié)議中,主動發(fā)起請求的一端為客戶端,被動連接的一端稱為服務(wù)端珍策。不管是客戶端還是服務(wù)端屯耸,TCP 連接建立完后都能發(fā)送和接收數(shù)據(jù),所以 TCP 也是一個全雙工的協(xié)議。
起初,兩端都為 CLOSED 狀態(tài)湾盗。在通信開始前,雙方都會創(chuàng)建 TCB。 服務(wù)器創(chuàng)建完 TCB 后遍進(jìn)入 LISTEN 狀態(tài),此時開始等待客戶端發(fā)送數(shù)據(jù)肤舞。
第一次握手
客戶端向服務(wù)端發(fā)送連接請求報文段囤耳。該報文段中包含自身的數(shù)據(jù)通訊初始序號。請求發(fā)送后,客戶端便進(jìn)入 SYN-SENT 狀態(tài),x
表示客戶端的數(shù)據(jù)通信初始序號。
第二次握手
服務(wù)端收到連接請求報文段后,如果同意連接夷磕,則會發(fā)送一個應(yīng)答绵跷,該應(yīng)答中也會包含自身的數(shù)據(jù)通訊初始序號荆残,發(fā)送完成后便進(jìn)入 SYN-RECEIVED 狀態(tài)俘闯。
第三次握手
當(dāng)客戶端收到連接同意的應(yīng)答后僧诚,還要向服務(wù)端發(fā)送一個確認(rèn)報文。客戶端發(fā)完這個報文段后便進(jìn)入ESTABLISHED 狀態(tài)琼锋,服務(wù)端收到這個應(yīng)答后也進(jìn)入 ESTABLISHED 狀態(tài),此時連接建立成功。
PS:第三次握手可以包含數(shù)據(jù)女仰,通過 TCP 快速打開(TFO)技術(shù)床三。其實只要涉及到握手的協(xié)議四瘫,都可以使用類似 TFO 的方式锹杈,客戶端和服務(wù)端存儲相同 cookie咬清,下次握手時發(fā)出 cookie 達(dá)到減少 RTT 的目的掘剪。
你是否有疑惑明明兩次握手就可以建立起連接匾鸥,為什么還需要第三次應(yīng)答劳曹?
因為這是為了防止失效的連接請求報文段被服務(wù)端接收账忘,從而產(chǎn)生錯誤蒋荚。
可以想象如下場景播赁√媾客戶端發(fā)送了一個連接請求 A阿趁,但是因為網(wǎng)絡(luò)原因造成了超時命黔,這時 TCP 會啟動超時重傳的機(jī)制再次發(fā)送一個連接請求 B洋魂。此時請求順利到達(dá)服務(wù)端角骤,服務(wù)端應(yīng)答完就建立了請求。如果連接請求 A 在兩端關(guān)閉后終于抵達(dá)了服務(wù)端捍掺,那么這時服務(wù)端會認(rèn)為客戶端又需要建立 TCP 連接不瓶,從而應(yīng)答了該請求并進(jìn)入 ESTABLISHED 狀態(tài)艳吠。此時客戶端其實是 CLOSED 狀態(tài)麦备,那么就會導(dǎo)致服務(wù)端一直等待,造成資源的浪費。
PS:在建立連接中凛篙,任意一端掉線黍匾,TCP 都會重發(fā) SYN 包呛梆,一般會重試五次填物,在建立連接中可能會遇到 SYN FLOOD 攻擊融痛。遇到這種情況你可以選擇調(diào)低重試次數(shù)或者干脆在不能處理的情況下拒絕請求雁刷。
斷開鏈接四次握手
TCP 是全雙工的责语,在斷開連接時兩端都需要發(fā)送 FIN 和 ACK目派。
第一次握手
若客戶端 A 認(rèn)為數(shù)據(jù)發(fā)送完成白筹,則它需要向服務(wù)端 B 發(fā)送連接釋放請求谅摄。
第二次握手
B 收到連接釋放請求后送漠,會告訴應(yīng)用層要釋放 TCP 鏈接闽寡。然后會發(fā)送 ACK 包爷狈,并進(jìn)入 CLOSE_WAIT 狀態(tài)淆院,表示 A 到 B 的連接已經(jīng)釋放土辩,不接收 A 發(fā)的數(shù)據(jù)了拷淘。但是因為 TCP 連接時雙向的启涯,所以 B 仍舊可以發(fā)送數(shù)據(jù)給 A结洼。
第三次握手
B 如果此時還有沒發(fā)完的數(shù)據(jù)會繼續(xù)發(fā)送蒸殿,完畢后會向 A 發(fā)送連接釋放請求宏所,然后 B 便進(jìn)入 LAST-ACK 狀態(tài)爬骤。
PS:通過延遲確認(rèn)的技術(shù)(通常有時間限制霞玄,否則對方會誤認(rèn)為需要重傳)溃列,可以將第二次和第三次握手合并听隐,延遲 ACK 包的發(fā)送雅任。
第四次握手
A 收到釋放請求后沪么,向 B 發(fā)送確認(rèn)應(yīng)答禽车,此時 A 進(jìn)入 TIME-WAIT 狀態(tài)州胳。該狀態(tài)會持續(xù) 2MSL(最大段生存期栓撞,指報文段在網(wǎng)絡(luò)中生存的時間瓤湘,超時會被拋棄) 時間弛说,若該時間段內(nèi)沒有 B 的重發(fā)請求的話,就進(jìn)入 CLOSED 狀態(tài)虎囚。當(dāng) B 收到確認(rèn)應(yīng)答后淘讥,也便進(jìn)入 CLOSED 狀態(tài)。
為什么 A 要進(jìn)入 TIME-WAIT 狀態(tài)蝗岖,等待 2MSL 時間后才進(jìn)入 CLOSED 狀態(tài)抵赢?
為了保證 B 能收到 A 的確認(rèn)應(yīng)答。若 A 發(fā)完確認(rèn)應(yīng)答后直接進(jìn)入 CLOSED 狀態(tài)邢享,如果確認(rèn)應(yīng)答因為網(wǎng)絡(luò)問題一直沒有到達(dá)骇塘,那么會造成 B 不能正常關(guān)閉唐瀑。
ARQ 協(xié)議
ARQ 協(xié)議也就是超時重傳機(jī)制座掘。通過確認(rèn)和超時機(jī)制保證了數(shù)據(jù)的正確送達(dá)溢陪,ARQ 協(xié)議包含停止等待 ARQ 和連續(xù) ARQ
停止等待 ARQ
正常傳輸過程
只要 A 向 B 發(fā)送一段報文形真,都要停止發(fā)送并啟動一個定時器咆霜,等待對端回應(yīng)光酣,在定時器時間內(nèi)接收到對端應(yīng)答就取消定時器并發(fā)送下一段報文救军。
報文丟失或出錯
在報文傳輸?shù)倪^程中可能會出現(xiàn)丟包。這時候超過定時器設(shè)定的時間就會再次發(fā)送丟包的數(shù)據(jù)直到對端響應(yīng),所以需要每次都備份發(fā)送的數(shù)據(jù)跌穗。
即使報文正常的傳輸?shù)綄Χ耍部赡艹霈F(xiàn)在傳輸過程中報文出錯的問題羹唠。這時候?qū)Χ藭仐壴搱笪牟⒌却?A 端重傳。
PS:一般定時器設(shè)定的時間都會大于一個 RTT 的平均時間佩微。
ACK 超時或丟失
對端傳輸?shù)膽?yīng)答也可能出現(xiàn)丟失或超時的情況。那么超過定時器時間 A 端照樣會重傳報文谷浅。這時候 B 端收到相同序號的報文會丟棄該報文并重傳應(yīng)答,直到 A 端發(fā)送下一個序號的報文。
在超時的情況下也可能出現(xiàn)應(yīng)答很遲到達(dá),這時 A 端會判斷該序號是否已經(jīng)接收過,如果接收過只需要丟棄應(yīng)答即可站削。
這個協(xié)議的缺點就是傳輸效率低菩鲜,在良好的網(wǎng)絡(luò)環(huán)境下每次發(fā)送報文都得等待對端的 ACK 猛频。
連續(xù) ARQ
在連續(xù) ARQ 中诽凌,發(fā)送端擁有一個發(fā)送窗口狱窘,可以在沒有收到應(yīng)答的情況下持續(xù)發(fā)送窗口內(nèi)的數(shù)據(jù)尖奔,這樣相比停止等待 ARQ 協(xié)議來說減少了等待時間淹禾,提高了效率丹弱。
累計確認(rèn)
連續(xù) ARQ 中纤勒,接收端會持續(xù)不斷收到報文。如果和停止等待 ARQ 中接收一個報文就發(fā)送一個應(yīng)答一樣,就太浪費資源了。通過累計確認(rèn),可以在收到多個報文以后統(tǒng)一回復(fù)一個應(yīng)答報文。報文中的 ACK 可以用來告訴發(fā)送端這個序號之前的數(shù)據(jù)已經(jīng)全部接收到了喘帚,下次請發(fā)送這個序號 + 1的數(shù)據(jù)朱嘴。
但是累計確認(rèn)也有一個弊端。在連續(xù)接收報文時,可能會遇到接收到序號 5 的報文后,并未接到序號 6 的報文,然而序號 7 以后的報文已經(jīng)接收朽色。遇到這種情況時,ACK 只能回復(fù) 6,這樣會造成發(fā)送端重復(fù)發(fā)送數(shù)據(jù),這種情況下可以通過 Sack 來解決,這個會在下文說到。
滑動窗口
在上面小節(jié)中講到了發(fā)送窗口。在 TCP 中悔详,兩端都維護(hù)著窗口:分別為發(fā)送端窗口和接收端窗口。
發(fā)送端窗口包含已發(fā)送但未收到應(yīng)答的數(shù)據(jù)和可以發(fā)送但是未發(fā)送的數(shù)據(jù)霜医。
發(fā)送端窗口是由接收窗口剩余大小決定的。接收方會把當(dāng)前接收窗口的剩余大小寫入應(yīng)答報文,發(fā)送端收到應(yīng)答后根據(jù)該值和當(dāng)前網(wǎng)絡(luò)擁塞情況設(shè)置發(fā)送窗口的大小埠偿,所以發(fā)送窗口的大小是不斷變化的抖剿。
當(dāng)發(fā)送端接收到應(yīng)答報文后,會隨之將窗口進(jìn)行滑動
滑動窗口實現(xiàn)了流量控制窿侈。接收方通過報文告知發(fā)送方還可以發(fā)送多少數(shù)據(jù)圆兵,從而保證接收方能夠來得及接收數(shù)據(jù)超凳。
Zero 窗口
在發(fā)送報文的過程中,可能會遇到對端出現(xiàn)零窗口的情況。在該情況下喜最,發(fā)送端會停止發(fā)送數(shù)據(jù)章咧,并啟動 persistent timer 卤档。該定時器會定時發(fā)送請求給對端舔腾,讓對端告知窗口大小。在重試次數(shù)超過一定次數(shù)后工扎,可能會中斷 TCP 鏈接而钞。
擁塞處理
擁塞處理和流量控制不同,后者是作用于接收方拘荡,保證接收方來得及接受數(shù)據(jù)臼节。而前者是作用于網(wǎng)絡(luò),防止過多的數(shù)據(jù)擁塞網(wǎng)絡(luò),避免出現(xiàn)網(wǎng)絡(luò)負(fù)載過大的情況网缝。
擁塞處理包括了四個算法巨税,分別為:慢開始,擁塞避免粉臊,快速重傳草添,快速恢復(fù)。
慢開始算法
慢開始算法扼仲,顧名思義远寸,就是在傳輸開始時將發(fā)送窗口慢慢指數(shù)級擴(kuò)大,從而避免一開始就傳輸大量數(shù)據(jù)導(dǎo)致網(wǎng)絡(luò)擁塞屠凶。
慢開始算法步驟具體如下
- 連接初始設(shè)置擁塞窗口(Congestion Window) 為 1 MSS(一個分段的最大數(shù)據(jù)量)
- 每過一個 RTT 就將窗口大小乘二
- 指數(shù)級增長肯定不能沒有限制的驰后,所以有一個閾值限制,當(dāng)窗口大小大于閾值時就會啟動擁塞避免算法矗愧。
擁塞避免算法
擁塞避免算法相比簡單點倡怎,每過一個 RTT 窗口大小只加一,這樣能夠避免指數(shù)級增長導(dǎo)致網(wǎng)絡(luò)擁塞贱枣,慢慢將大小調(diào)整到最佳值监署。
在傳輸過程中可能定時器超時的情況,這時候 TCP 會認(rèn)為網(wǎng)絡(luò)擁塞了纽哥,會馬上進(jìn)行以下步驟:
- 將閾值設(shè)為當(dāng)前擁塞窗口的一半
- 將擁塞窗口設(shè)為 1 MSS
- 啟動擁塞避免算法
快速重傳
快速重傳一般和快恢復(fù)一起出現(xiàn)钠乏。一旦接收端收到的報文出現(xiàn)失序的情況,接收端只會回復(fù)最后一個順序正確的報文序號(沒有 Sack 的情況下)春塌。如果收到三個重復(fù)的 ACK晓避,無需等待定時器超時再重發(fā)而是啟動快速重傳。具體算法分為兩種:
TCP Taho 實現(xiàn)如下
- 將閾值設(shè)為當(dāng)前擁塞窗口的一半
- 將擁塞窗口設(shè)為 1 MSS
- 重新開始慢開始算法
TCP Reno 實現(xiàn)如下
- 擁塞窗口減半
- 將閾值設(shè)為當(dāng)前擁塞窗口
- 進(jìn)入快恢復(fù)階段(重發(fā)對端需要的包只壳,一旦收到一個新的 ACK 答復(fù)就退出該階段)
- 使用擁塞避免算法
TCP New Ren 改進(jìn)后的快恢復(fù)
TCP New Reno 算法改進(jìn)了之前 TCP Reno 算法的缺陷俏拱。在之前,快恢復(fù)中只要收到一個新的 ACK 包吼句,就會退出快恢復(fù)锅必。
在 TCP New Reno 中,TCP 發(fā)送方先記下三個重復(fù) ACK 的分段的最大序號惕艳。
假如我有一個分段數(shù)據(jù)是 1 ~ 10 這十個序號的報文搞隐,其中丟失了序號為 3 和 7 的報文,那么該分段的最大序號就是 10远搪。發(fā)送端只會收到 ACK 序號為 3 的應(yīng)答劣纲。這時候重發(fā)序號為 3 的報文,接收方順利接收并會發(fā)送 ACK 序號為 7 的應(yīng)答谁鳍。這時候 TCP 知道對端是有多個包未收到癞季,會繼續(xù)發(fā)送序號為 7 的報文劫瞳,接收方順利接收并會發(fā)送 ACK 序號為 11 的應(yīng)答,這時發(fā)送端認(rèn)為這個分段接收端已經(jīng)順利接收绷柒,接下來會退出快恢復(fù)階段柠新。
HTTP
HTTP 協(xié)議是個無狀態(tài)協(xié)議,不會保存狀態(tài)辉巡。
Post 和 Get 的區(qū)別
先引入副作用和冪等的概念恨憎。
副作用指對服務(wù)器上的資源做改變,搜索是無副作用的郊楣,注冊是副作用的憔恳。
冪等指發(fā)送 M 和 N 次請求(兩者不相同且都大于 1),服務(wù)器上資源的狀態(tài)一致净蚤,比如注冊 10 個和 11 個帳號是不冪等的钥组,對文章進(jìn)行更改 10 次和 11 次是冪等的。
在規(guī)范的應(yīng)用場景上說今瀑,Get 多用于無副作用程梦,冪等的場景,例如搜索關(guān)鍵字橘荠。Post 多用于副作用屿附,不冪等的場景,例如注冊哥童。
在技術(shù)上說:
- Get 請求能緩存挺份,Post 不能
- Post 相對 Get 安全一點點,因為Get 請求都包含在 URL 里贮懈,且會被瀏覽器保存歷史紀(jì)錄匀泊,Post 不會,但是在抓包的情況下都是一樣的朵你。
- Post 可以通過 request body來傳輸比 Get 更多的數(shù)據(jù)各聘,Get 沒有這個技術(shù)
- URL有長度限制,會影響 Get 請求抡医,但是這個長度限制是瀏覽器規(guī)定的躲因,不是 RFC 規(guī)定的
- Post 支持更多的編碼類型且不對數(shù)據(jù)類型限制
常見狀態(tài)碼
2XX 成功
- 200 OK,表示從客戶端發(fā)來的請求在服務(wù)器端被正確處理
- 204 No content魂拦,表示請求成功毛仪,但響應(yīng)報文不含實體的主體部分
- 205 Reset Content,表示請求成功芯勘,但響應(yīng)報文不含實體的主體部分,但是與 204 響應(yīng)不同在于要求請求方重置內(nèi)容
- 206 Partial Content腺逛,進(jìn)行范圍請求
3XX 重定向
- 301 moved permanently荷愕,永久性重定向,表示資源已被分配了新的 URL
- 302 found,臨時性重定向安疗,表示資源臨時被分配了新的 URL
- 303 see other抛杨,表示資源存在著另一個 URL,應(yīng)使用 GET 方法獲取資源
- 304 not modified荐类,表示服務(wù)器允許訪問資源怖现,但因發(fā)生請求未滿足條件的情況
- 307 temporary redirect,臨時重定向玉罐,和302含義類似屈嗤,但是期望客戶端保持請求方法不變向新的地址發(fā)出請求
4XX 客戶端錯誤
- 400 bad request,請求報文存在語法錯誤
- 401 unauthorized吊输,表示發(fā)送的請求需要有通過 HTTP 認(rèn)證的認(rèn)證信息
- 403 forbidden饶号,表示對請求資源的訪問被服務(wù)器拒絕
- 404 not found,表示在服務(wù)器上沒有找到請求的資源
5XX 服務(wù)器錯誤
- 500 internal sever error季蚂,表示服務(wù)器端在執(zhí)行請求時發(fā)生了錯誤
- 501 Not Implemented茫船,表示服務(wù)器不支持當(dāng)前請求所需要的某個功能
- 503 service unavailable,表明服務(wù)器暫時處于超負(fù)載或正在停機(jī)維護(hù)扭屁,無法處理請求
HTTP 首部
通用字段 | 作用 |
---|---|
Cache-Control | 控制緩存的行為 |
Connection | 瀏覽器想要優(yōu)先使用的連接類型算谈,比如 keep-alive
|
Date | 創(chuàng)建報文時間 |
Pragma | 報文指令 |
Via | 代理服務(wù)器相關(guān)信息 |
Transfer-Encoding | 傳輸編碼方式 |
Upgrade | 要求客戶端升級協(xié)議 |
Warning | 在內(nèi)容中可能存在錯誤 |
請求字段 | 作用 |
---|---|
Accept | 能正確接收的媒體類型 |
Accept-Charset | 能正確接收的字符集 |
Accept-Encoding | 能正確接收的編碼格式列表 |
Accept-Language | 能正確接收的語言列表 |
Expect | 期待服務(wù)端的指定行為 |
From | 請求方郵箱地址 |
Host | 服務(wù)器的域名 |
If-Match | 兩端資源標(biāo)記比較 |
If-Modified-Since | 本地資源未修改返回 304(比較時間) |
If-None-Match | 本地資源未修改返回 304(比較標(biāo)記) |
User-Agent | 客戶端信息 |
Max-Forwards | 限制可被代理及網(wǎng)關(guān)轉(zhuǎn)發(fā)的次數(shù) |
Proxy-Authorization | 向代理服務(wù)器發(fā)送驗證信息 |
Range | 請求某個內(nèi)容的一部分 |
Referer | 表示瀏覽器所訪問的前一個頁面 |
TE | 傳輸編碼方式 |
響應(yīng)字段 | 作用 |
---|---|
Accept-Ranges | 是否支持某些種類的范圍 |
Age | 資源在代理緩存中存在的時間 |
ETag | 資源標(biāo)識 |
Location | 客戶端重定向到某個 URL |
Proxy-Authenticate | 向代理服務(wù)器發(fā)送驗證信息 |
Server | 服務(wù)器名字 |
WWW-Authenticate | 獲取資源需要的驗證信息 |
實體字段 | 作用 |
---|---|
Allow | 資源的正確請求方式 |
Content-Encoding | 內(nèi)容的編碼格式 |
Content-Language | 內(nèi)容使用的語言 |
Content-Length | request body 長度 |
Content-Location | 返回數(shù)據(jù)的備用地址 |
Content-MD5 | Base64加密格式的內(nèi)容 MD5檢驗值 |
Content-Range | 內(nèi)容的位置范圍 |
Content-Type | 內(nèi)容的媒體類型 |
Expires | 內(nèi)容的過期時間 |
Last_modified | 內(nèi)容的最后修改時間 |
PS:緩存相關(guān)已在別的模塊中寫完,你可以 閱讀該小節(jié)
HTTPS
HTTPS 還是通過了 HTTP 來傳輸信息料滥,但是信息通過 TLS 協(xié)議進(jìn)行了加密濒生。
TLS
TLS 協(xié)議位于傳輸層之上,應(yīng)用層之下幔欧。首次進(jìn)行 TLS 協(xié)議傳輸需要兩個 RTT 罪治,接下來可以通過 Session Resumption 減少到一個 RTT。
在 TLS 中使用了兩種加密技術(shù)礁蔗,分別為:對稱加密和非對稱加密觉义。
對稱加密:
對稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密浴井。
非對稱加密:
有公鑰私鑰之分晒骇,公鑰所有人都可以知道,可以將數(shù)據(jù)用公鑰加密磺浙,但是將數(shù)據(jù)解密必須使用私鑰解密洪囤,私鑰只有分發(fā)公鑰的一方才知道。
TLS 握手過程如下圖:
[圖片上傳失敗...(image-9e840c-1543831239746)]
- 客戶端發(fā)送一個隨機(jī)值撕氧,需要的協(xié)議和加密方式
- 服務(wù)端收到客戶端的隨機(jī)值瘤缩,自己也產(chǎn)生一個隨機(jī)值,并根據(jù)客戶端需求的協(xié)議和加密方式來使用對應(yīng)的方式伦泥,發(fā)送自己的證書(如果需要驗證客戶端證書需要說明)
- 客戶端收到服務(wù)端的證書并驗證是否有效剥啤,驗證通過會再生成一個隨機(jī)值锦溪,通過服務(wù)端證書的公鑰去加密這個隨機(jī)值并發(fā)送給服務(wù)端,如果服務(wù)端需要驗證客戶端證書的話會附帶證書
- 服務(wù)端收到加密過的隨機(jī)值并使用私鑰解密獲得第三個隨機(jī)值府怯,這時候兩端都擁有了三個隨機(jī)值刻诊,可以通過這三個隨機(jī)值按照之前約定的加密方式生成密鑰,接下來的通信就可以通過該密鑰來加密解密
通過以上步驟可知牺丙,在 TLS 握手階段则涯,兩端使用非對稱加密的方式來通信,但是因為非對稱加密損耗的性能比對稱加密大冲簿,所以在正式傳輸數(shù)據(jù)時粟判,兩端使用對稱加密的方式通信。
PS:以上說明的都是 TLS 1.2 協(xié)議的握手情況民假,在 1.3 協(xié)議中浮入,首次建立連接只需要一個 RTT,后面恢復(fù)連接不需要 RTT 了羊异。
HTTP 2.0
HTTP 2.0 相比于 HTTP 1.X事秀,可以說是大幅度提高了 web 的性能。
在 HTTP 1.X 中野舶,為了性能考慮易迹,我們會引入雪碧圖、將小圖內(nèi)聯(lián)平道、使用多個域名等等的方式睹欲。這一切都是因為瀏覽器限制了同一個域名下的請求數(shù)量,當(dāng)頁面中需要請求很多資源的時候一屋,隊頭阻塞(Head of line blocking)會導(dǎo)致在達(dá)到最大請求數(shù)量時窘疮,剩余的資源需要等待其他資源請求完成后才能發(fā)起請求。
你可以通過 該鏈接 感受下 HTTP 2.0 比 HTTP 1.X 到底快了多少冀墨。
在 HTTP 1.X 中闸衫,因為隊頭阻塞的原因,你會發(fā)現(xiàn)請求是這樣的
在 HTTP 2.0 中诽嘉,因為引入了多路復(fù)用蔚出,你會發(fā)現(xiàn)請求是這樣的
二進(jìn)制傳輸
HTTP 2.0 中所有加強性能的核心點在于此。在之前的 HTTP 版本中虫腋,我們是通過文本的方式傳輸數(shù)據(jù)骄酗。在 HTTP 2.0 中引入了新的編碼機(jī)制,所有傳輸?shù)臄?shù)據(jù)都會被分割悦冀,并采用二進(jìn)制格式編碼趋翻。
多路復(fù)用
在 HTTP 2.0 中,有兩個非常重要的概念雏门,分別是幀(frame)和流(stream)嘿歌。
幀代表著最小的數(shù)據(jù)單位掸掏,每個幀會標(biāo)識出該幀屬于哪個流茁影,流也就是多個幀組成的數(shù)據(jù)流宙帝。
多路復(fù)用,就是在一個 TCP 連接中可以存在多條流募闲。換句話說步脓,也就是可以發(fā)送多個請求,對端可以通過幀中的標(biāo)識知道屬于哪個請求浩螺。通過這個技術(shù)靴患,可以避免 HTTP 舊版本中的隊頭阻塞問題,極大的提高傳輸性能要出。
Header 壓縮
在 HTTP 1.X 中鸳君,我們使用文本的形式傳輸 header,在 header 攜帶 cookie 的情況下患蹂,可能每次都需要重復(fù)傳輸幾百到幾千的字節(jié)或颊。
在 HTTP 2.0 中,使用了 HPACK 壓縮格式對傳輸?shù)?header 進(jìn)行編碼传于,減少了 header 的大小囱挑。并在兩端維護(hù)了索引表,用于記錄出現(xiàn)過的 header 沼溜,后面在傳輸過程中就可以傳輸已經(jīng)記錄過的 header 的鍵名平挑,對端收到數(shù)據(jù)后就可以通過鍵名找到對應(yīng)的值。
服務(wù)端 Push
在 HTTP 2.0 中系草,服務(wù)端可以在客戶端某個請求后通熄,主動推送其他資源。
可以想象以下情況找都,某些資源客戶端是一定會請求的唇辨,這時就可以采取服務(wù)端 push 的技術(shù),提前給客戶端推送必要的資源檐嚣,這樣就可以相對減少一點延遲時間助泽。當(dāng)然在瀏覽器兼容的情況下你也可以使用 prefetch 。
QUIC
這是一個谷歌出品的基于 UDP 實現(xiàn)的同為傳輸層的協(xié)議嚎京,目標(biāo)很遠(yuǎn)大嗡贺,希望替代 TCP 協(xié)議。
- 該協(xié)議支持多路復(fù)用鞍帝,雖然 HTTP 2.0 也支持多路復(fù)用诫睬,但是下層仍是 TCP,因為 TCP 的重傳機(jī)制帕涌,只要一個包丟失就得判斷丟失包并且重傳摄凡,導(dǎo)致發(fā)生隊頭阻塞的問題续徽,但是 UDP 沒有這個機(jī)制
- 實現(xiàn)了自己的加密協(xié)議,通過類似 TCP 的 TFO 機(jī)制可以實現(xiàn) 0-RTT亲澡,當(dāng)然 TLS 1.3 已經(jīng)實現(xiàn)了 0-RTT 了
- 支持重傳和糾錯機(jī)制(向前恢復(fù))钦扭,在只丟失一個包的情況下不需要重傳,使用糾錯機(jī)制恢復(fù)丟失的包
- 糾錯機(jī)制:通過異或的方式床绪,算出發(fā)出去的數(shù)據(jù)的異或值并單獨發(fā)出一個包客情,服務(wù)端在發(fā)現(xiàn)有一個包丟失的情況下,通過其他數(shù)據(jù)包和異或值包算出丟失包
- 在丟失兩個包或以上的情況就使用重傳機(jī)制癞己,因為算不出來了
DNS
DNS 的作用就是通過域名查詢到具體的 IP膀斋。
因為 IP 存在數(shù)字和英文的組合(IPv6),很不利于人類記憶痹雅,所以就出現(xiàn)了域名仰担。你可以把域名看成是某個 IP 的別名,DNS 就是去查詢這個別名的真正名稱是什么绩社。
在 TCP 握手之前就已經(jīng)進(jìn)行了 DNS 查詢摔蓝,這個查詢是操作系統(tǒng)自己做的。當(dāng)你在瀏覽器中想訪問 www.google.com
時铃将,會進(jìn)行一下操作:
- 操作系統(tǒng)會首先在本地緩存中查詢
- 沒有的話會去系統(tǒng)配置的 DNS 服務(wù)器中查詢
- 如果這時候還沒得話项鬼,會直接去 DNS 根服務(wù)器查詢,這一步查詢會找出負(fù)責(zé)
com
這個一級域名的服務(wù)器 - 然后去該服務(wù)器查詢
google
這個二級域名 - 接下來三級域名的查詢其實是我們配置的劲阎,你可以給
www
這個域名配置一個 IP绘盟,然后還可以給別的三級域名配置一個 IP
以上介紹的是 DNS 迭代查詢,還有種是遞歸查詢悯仙,區(qū)別就是前者是由客戶端去做請求龄毡,后者是由系統(tǒng)配置的 DNS 服務(wù)器做請求,得到結(jié)果后將數(shù)據(jù)返回給客戶端锡垄。
PS:DNS 是基于 UDP 做的查詢沦零。
從輸入 URL 到頁面加載完成的過程
這是一個很經(jīng)典的面試題,在這題中可以將本文講得內(nèi)容都串聯(lián)起來货岭。
- 首先做 DNS 查詢路操,如果這一步做了智能 DNS 解析的話,會提供訪問速度最快的 IP 地址回來
- 接下來是 TCP 握手千贯,應(yīng)用層會下發(fā)數(shù)據(jù)給傳輸層屯仗,這里 TCP 協(xié)議會指明兩端的端口號,然后下發(fā)給網(wǎng)絡(luò)層搔谴。網(wǎng)絡(luò)層中的 IP 協(xié)議會確定 IP 地址魁袜,并且指示了數(shù)據(jù)傳輸中如何跳轉(zhuǎn)路由器。然后包會再被封裝到數(shù)據(jù)鏈路層的數(shù)據(jù)幀結(jié)構(gòu)中,最后就是物理層面的傳輸了
- TCP 握手結(jié)束后會進(jìn)行 TLS 握手峰弹,然后就開始正式的傳輸數(shù)據(jù)
- 數(shù)據(jù)在進(jìn)入服務(wù)端之前店量,可能還會先經(jīng)過負(fù)責(zé)負(fù)載均衡的服務(wù)器,它的作用就是將請求合理的分發(fā)到多臺服務(wù)器上鞠呈,這時假設(shè)服務(wù)端會響應(yīng)一個 HTML 文件
- 首先瀏覽器會判斷狀態(tài)碼是什么融师,如果是 200 那就繼續(xù)解析,如果 400 或 500 的話就會報錯粟按,如果 300 的話會進(jìn)行重定向诬滩,這里會有個重定向計數(shù)器霹粥,避免過多次的重定向灭将,超過次數(shù)也會報錯
- 瀏覽器開始解析文件,如果是 gzip 格式的話會先解壓一下后控,然后通過文件的編碼格式知道該如何去解碼文件
- 文件解碼成功后會正式開始渲染流程庙曙,先會根據(jù) HTML 構(gòu)建 DOM 樹,有 CSS 的話會去構(gòu)建 CSSOM 樹浩淘。如果遇到
script
標(biāo)簽的話捌朴,會判斷是否存在async
或者defer
,前者會并行進(jìn)行下載并執(zhí)行 JS张抄,后者會先下載文件砂蔽,然后等待 HTML 解析完成后順序執(zhí)行,如果以上都沒有署惯,就會阻塞住渲染流程直到 JS 執(zhí)行完畢左驾。遇到文件下載的會去下載文件,這里如果使用 HTTP 2.0 協(xié)議的話會極大的提高多圖的下載效率极谊。 - 初始的 HTML 被完全加載和解析后會觸發(fā)
DOMContentLoaded
事件 - CSSOM 樹和 DOM 樹構(gòu)建完成后會開始生成 Render 樹诡右,這一步就是確定頁面元素的布局、樣式等等諸多方面的東西
- 在生成 Render 樹的過程中轻猖,瀏覽器就開始調(diào)用 GPU 繪制逼争,合成圖層前痘,將內(nèi)容顯示在屏幕上了