摘要:這時(shí)候超過定時(shí)器設(shè)定的時(shí)間就會(huì)再次發(fā)送丟包的數(shù)據(jù)直到對端響應(yīng),所以需要每次都備份發(fā)送的數(shù)據(jù)。
UDP 面向報(bào)文
UDP 是一個(gè)面向報(bào)文(報(bào)文可以理解為一段段的數(shù)據(jù))的協(xié)議。意思就是 UDP 只是報(bào)文的搬運(yùn)工,不會(huì)對報(bào)文進(jìn)行任何拆分和拼接操作。
具體來說
在發(fā)送端,應(yīng)用層將數(shù)據(jù)傳遞給傳輸層的 UDP 協(xié)議,UDP 只會(huì)給數(shù)據(jù)增加一個(gè) UDP 頭標(biāo)識下是 UDP 協(xié)議,然后就傳遞給網(wǎng)絡(luò)層了
在接收端,網(wǎng)絡(luò)層將數(shù)據(jù)傳遞給傳輸層,UDP 只去除 IP 報(bào)文頭就傳遞給應(yīng)用層,不會(huì)任何拼接操作
不可靠性UDP 是無連接的,也就是說通信不需要建立和斷開連接。
UDP 也是不可靠的。協(xié)議收到什么數(shù)據(jù)就傳遞什么數(shù)據(jù),并且也不會(huì)備份數(shù)據(jù),對方能不能收到是不關(guān)心的
UDP 沒有擁塞控制,一直會(huì)以恒定的速度發(fā)送數(shù)據(jù)。即使網(wǎng)絡(luò)條件不好,也不會(huì)對發(fā)送速率進(jìn)行調(diào)整。這樣實(shí)現(xiàn)的弊端就是在網(wǎng)絡(luò)條件不好的情況下可能會(huì)導(dǎo)致丟包,但是優(yōu)點(diǎn)也很明顯,在某些實(shí)時(shí)性要求高的場景(比如電話會(huì)議)就需要使用 UDP 而不是 TCP。
高效因?yàn)?UDP 沒有 TCP 那么復(fù)雜,需要保證數(shù)據(jù)不丟失且有序到達(dá)。所以 UDP 的頭部開銷小,只有八字節(jié),相比 TCP 的至少二十字節(jié)要少得多,在傳輸數(shù)據(jù)報(bào)文時(shí)是很高效的。
頭部包含了以下幾個(gè)數(shù)據(jù)
兩個(gè)十六位的端口號,分別為源端口(可選字段)和目標(biāo)端口
整個(gè)數(shù)據(jù)報(bào)文的長度
整個(gè)數(shù)據(jù)報(bào)文的檢驗(yàn)和(IPv4 可選 字段),該字段用于發(fā)現(xiàn)頭部信息和數(shù)據(jù)中的錯(cuò)誤
傳輸方式UDP 不止支持一對一的傳輸方式,同樣支持一對多,多對多,多對一的方式,也就是說 UDP 提供了單播,多播,廣播的功能。
TCP 頭部TCP 頭部比 UDP 頭部復(fù)雜的多
對于 TCP 頭部來說,以下幾個(gè)字段是很重要的
Sequence number,這個(gè)序號保證了 TCP 傳輸?shù)膱?bào)文都是有序的,對端可以通過序號順序的拼接報(bào)文
Acknowledgement Number,這個(gè)序號表示數(shù)據(jù)接收端期望接收的下一個(gè)字節(jié)的編號是多少,同時(shí)也表示上一個(gè)序號的數(shù)據(jù)已經(jīng)收到
Window Size,窗口大小,表示還能接收多少字節(jié)的數(shù)據(jù),用于流量控制
標(biāo)識符
URG=1:該字段為一表示本數(shù)據(jù)報(bào)的數(shù)據(jù)部分包含緊急信息,是一個(gè)高優(yōu)先級數(shù)據(jù)報(bào)文,此時(shí)緊急指針有效。緊急數(shù)據(jù)一定位于當(dāng)前數(shù)據(jù)包數(shù)據(jù)部分的最前面,緊急指針標(biāo)明了緊急數(shù)據(jù)的尾部。
ACK=1:該字段為一表示確認(rèn)號字段有效。此外,TCP 還規(guī)定在連接建立后傳送的所有報(bào)文段都必須把 ACK 置為一。
PSH=1:該字段為一表示接收端應(yīng)該立即將數(shù)據(jù) push 給應(yīng)用層,而不是等到緩沖區(qū)滿后再提交。
RST=1:該字段為一表示當(dāng)前 TCP 連接出現(xiàn)嚴(yán)重問題,可能需要重新建立 TCP 連接,也可以用于拒絕非法的報(bào)文段和拒絕連接請求。
SYN=1:當(dāng)SYN=1,ACK=0時(shí),表示當(dāng)前報(bào)文段是一個(gè)連接請求報(bào)文。當(dāng)SYN=1,ACK=1時(shí),表示當(dāng)前報(bào)文段是一個(gè)同意建立連接的應(yīng)答報(bào)文。
FIN=1:該字段為一表示此報(bào)文段是一個(gè)釋放連接的請求報(bào)文。
狀態(tài)機(jī)HTTP 是無連接的,所以作為下層的 TCP 協(xié)議也是無連接的,雖然看似 TCP 將兩端連接了起來,但是其實(shí)只是兩端共同維護(hù)了一個(gè)狀態(tài)
TCP 的狀態(tài)機(jī)是很復(fù)雜的,并且與建立斷開連接時(shí)的握手息息相關(guān),接下來就來詳細(xì)描述下兩種握手。
在這之前需要了解一個(gè)重要的性能指標(biāo) RTT。該指標(biāo)表示發(fā)送端發(fā)送數(shù)據(jù)到接收到對端數(shù)據(jù)所需的往返時(shí)間。
建立連接三次握手在 TCP 協(xié)議中,主動(dòng)發(fā)起請求的一端為客戶端,被動(dòng)連接的一端稱為服務(wù)端。不管是客戶端還是服務(wù)端,TCP 連接建立完后都能發(fā)送和接收數(shù)據(jù),所以 TCP 也是一個(gè)全雙工的協(xié)議。
起初,兩端都為 CLOSED 狀態(tài)。在通信開始前,雙方都會(huì)創(chuàng)建 TCB。 服務(wù)器創(chuàng)建完 TCB 后遍進(jìn)入 LISTEN 狀態(tài),此時(shí)開始等待客戶端發(fā)送數(shù)據(jù)。
第一次握手
客戶端向服務(wù)端發(fā)送連接請求報(bào)文段。該報(bào)文段中包含自身的數(shù)據(jù)通訊初始序號。請求發(fā)送后,客戶端便進(jìn)入 SYN-SENT 狀態(tài),x 表示客戶端的數(shù)據(jù)通信初始序號。
第二次握手
服務(wù)端收到連接請求報(bào)文段后,如果同意連接,則會(huì)發(fā)送一個(gè)應(yīng)答,該應(yīng)答中也會(huì)包含自身的數(shù)據(jù)通訊初始序號,發(fā)送完成后便進(jìn)入 SYN-RECEIVED 狀態(tài)。
第三次握手
當(dāng)客戶端收到連接同意的應(yīng)答后,還要向服務(wù)端發(fā)送一個(gè)確認(rèn)報(bào)文??蛻舳税l(fā)完這個(gè)報(bào)文段后便進(jìn)入ESTABLISHED 狀態(tài),服務(wù)端收到這個(gè)應(yīng)答后也進(jìn)入 ESTABLISHED 狀態(tài),此時(shí)連接建立成功。
PS:第三次握手可以包含數(shù)據(jù),通過 TCP 快速打開(TFO)技術(shù)。其實(shí)只要涉及到握手的協(xié)議,都可以使用類似 TFO 的方式,客戶端和服務(wù)端存儲相同 cookie,下次握手時(shí)發(fā)出 cookie 達(dá)到減少 RTT 的目的。
你是否有疑惑明明兩次握手就可以建立起連接,為什么還需要第三次應(yīng)答?
因?yàn)檫@是為了防止失效的連接請求報(bào)文段被服務(wù)端接收,從而產(chǎn)生錯(cuò)誤。
可以想象如下場景??蛻舳税l(fā)送了一個(gè)連接請求 A,但是因?yàn)榫W(wǎng)絡(luò)原因造成了超時(shí),這時(shí) TCP 會(huì)啟動(dòng)超時(shí)重傳的機(jī)制再次發(fā)送一個(gè)連接請求 B。此時(shí)請求順利到達(dá)服務(wù)端,服務(wù)端應(yīng)答完就建立了請求。如果連接請求 A 在兩端關(guān)閉后終于抵達(dá)了服務(wù)端,那么這時(shí)服務(wù)端會(huì)認(rèn)為客戶端又需要建立 TCP 連接,從而應(yīng)答了該請求并進(jìn)入 ESTABLISHED 狀態(tài)。此時(shí)客戶端其實(shí)是 CLOSED 狀態(tài),那么就會(huì)導(dǎo)致服務(wù)端一直等待,造成資源的浪費(fèi)。
PS:在建立連接中,任意一端掉線,TCP 都會(huì)重發(fā) SYN 包,一般會(huì)重試五次,在建立連接中可能會(huì)遇到 SYN FLOOD 攻擊。遇到這種情況你可以選擇調(diào)低重試次數(shù)或者干脆在不能處理的情況下拒絕請求。
斷開鏈接四次握手TCP 是全雙工的,在斷開連接時(shí)兩端都需要發(fā)送 FIN 和 ACK。
第一次握手
若客戶端 A 認(rèn)為數(shù)據(jù)發(fā)送完成,則它需要向服務(wù)端 B 發(fā)送連接釋放請求。
第二次握手
B 收到連接釋放請求后,會(huì)告訴應(yīng)用層要釋放 TCP 鏈接。然后會(huì)發(fā)送 ACK 包,并進(jìn)入 CLOSE_WAIT 狀態(tài),表示 A 到 B 的連接已經(jīng)釋放,不接收 A 發(fā)的數(shù)據(jù)了。但是因?yàn)?TCP 連接時(shí)雙向的,所以 B 仍舊可以發(fā)送數(shù)據(jù)給 A。
第三次握手
B 如果此時(shí)還有沒發(fā)完的數(shù)據(jù)會(huì)繼續(xù)發(fā)送,完畢后會(huì)向 A 發(fā)送連接釋放請求,然后 B 便進(jìn)入 LAST-ACK 狀態(tài)。
PS:通過延遲確認(rèn)的技術(shù)(通常有時(shí)間限制,否則對方會(huì)誤認(rèn)為需要重傳),可以將第二次和第三次握手合并,延遲 ACK 包的發(fā)送。
第四次握手
A 收到釋放請求后,向 B 發(fā)送確認(rèn)應(yīng)答,此時(shí) A 進(jìn)入 TIME-WAIT 狀態(tài)。該狀態(tài)會(huì)持續(xù) 2MSL(最大段生存期,指報(bào)文段在網(wǎng)絡(luò)中生存的時(shí)間,超時(shí)會(huì)被拋棄) 時(shí)間,若該時(shí)間段內(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 時(shí)間后才進(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)答因?yàn)榫W(wǎng)絡(luò)問題一直沒有到達(dá),那么會(huì)造成 B 不能正常關(guān)閉。
ARQ 協(xié)議ARQ 協(xié)議也就是超時(shí)重傳機(jī)制。通過確認(rèn)和超時(shí)機(jī)制保證了數(shù)據(jù)的正確送達(dá),ARQ 協(xié)議包含停止等待 ARQ 和連續(xù) ARQ
停止等待 ARQ正常傳輸過程
只要 A 向 B 發(fā)送一段報(bào)文,都要停止發(fā)送并啟動(dòng)一個(gè)定時(shí)器,等待對端回應(yīng),在定時(shí)器時(shí)間內(nèi)接收到對端應(yīng)答就取消定時(shí)器并發(fā)送下一段報(bào)文。
報(bào)文丟失或出錯(cuò)
在報(bào)文傳輸?shù)倪^程中可能會(huì)出現(xiàn)丟包。這時(shí)候超過定時(shí)器設(shè)定的時(shí)間就會(huì)再次發(fā)送丟包的數(shù)據(jù)直到對端響應(yīng),所以需要每次都備份發(fā)送的數(shù)據(jù)。
即使報(bào)文正常的傳輸?shù)綄Χ?,也可能出現(xiàn)在傳輸過程中報(bào)文出錯(cuò)的問題。這時(shí)候?qū)Χ藭?huì)拋棄該報(bào)文并等待 A 端重傳。
PS:一般定時(shí)器設(shè)定的時(shí)間都會(huì)大于一個(gè) RTT 的平均時(shí)間。
ACK 超時(shí)或丟失
對端傳輸?shù)膽?yīng)答也可能出現(xiàn)丟失或超時(shí)的情況。那么超過定時(shí)器時(shí)間 A 端照樣會(huì)重傳報(bào)文。這時(shí)候 B 端收到相同序號的報(bào)文會(huì)丟棄該報(bào)文并重傳應(yīng)答,直到 A 端發(fā)送下一個(gè)序號的報(bào)文。
在超時(shí)的情況下也可能出現(xiàn)應(yīng)答很遲到達(dá),這時(shí) A 端會(huì)判斷該序號是否已經(jīng)接收過,如果接收過只需要丟棄應(yīng)答即可。
這個(gè)協(xié)議的缺點(diǎn)就是傳輸效率低,在良好的網(wǎng)絡(luò)環(huán)境下每次發(fā)送報(bào)文都得等待對端的 ACK 。
連續(xù) ARQ在連續(xù) ARQ 中,發(fā)送端擁有一個(gè)發(fā)送窗口,可以在沒有收到應(yīng)答的情況下持續(xù)發(fā)送窗口內(nèi)的數(shù)據(jù),這樣相比停止等待 ARQ 協(xié)議來說減少了等待時(shí)間,提高了效率。
累計(jì)確認(rèn)連續(xù) ARQ 中,接收端會(huì)持續(xù)不斷收到報(bào)文。如果和停止等待 ARQ 中接收一個(gè)報(bào)文就發(fā)送一個(gè)應(yīng)答一樣,就太浪費(fèi)資源了。通過累計(jì)確認(rèn),可以在收到多個(gè)報(bào)文以后統(tǒng)一回復(fù)一個(gè)應(yīng)答報(bào)文。報(bào)文中的 ACK 可以用來告訴發(fā)送端這個(gè)序號之前的數(shù)據(jù)已經(jīng)全部接收到了,下次請發(fā)送這個(gè)序號 + 1的數(shù)據(jù)。
但是累計(jì)確認(rèn)也有一個(gè)弊端。在連續(xù)接收報(bào)文時(shí),可能會(huì)遇到接收到序號 5 的報(bào)文后,并未接到序號 6 的報(bào)文,然而序號 7 以后的報(bào)文已經(jīng)接收。遇到這種情況時(shí),ACK 只能回復(fù) 6,這樣會(huì)造成發(fā)送端重復(fù)發(fā)送數(shù)據(jù),這種情況下可以通過 Sack 來解決,這個(gè)會(huì)在下文說到。
滑動(dòng)窗口在上面小節(jié)中講到了發(fā)送窗口。在 TCP 中,兩端都維護(hù)著窗口:分別為發(fā)送端窗口和接收端窗口。
發(fā)送端窗口包含已發(fā)送但未收到應(yīng)答的數(shù)據(jù)和可以發(fā)送但是未發(fā)送的數(shù)據(jù)。
發(fā)送端窗口是由接收窗口剩余大小決定的。接收方會(huì)把當(dāng)前接收窗口的剩余大小寫入應(yīng)答報(bào)文,發(fā)送端收到應(yīng)答后根據(jù)該值和當(dāng)前網(wǎng)絡(luò)擁塞情況設(shè)置發(fā)送窗口的大小,所以發(fā)送窗口的大小是不斷變化的。
當(dāng)發(fā)送端接收到應(yīng)答報(bào)文后,會(huì)隨之將窗口進(jìn)行滑動(dòng)
滑動(dòng)窗口實(shí)現(xiàn)了流量控制。接收方通過報(bào)文告知發(fā)送方還可以發(fā)送多少數(shù)據(jù),從而保證接收方能夠來得及接收數(shù)據(jù)。
Zero 窗口在發(fā)送報(bào)文的過程中,可能會(huì)遇到對端出現(xiàn)零窗口的情況。在該情況下,發(fā)送端會(huì)停止發(fā)送數(shù)據(jù),并啟動(dòng) persistent timer 。該定時(shí)器會(huì)定時(shí)發(fā)送請求給對端,讓對端告知窗口大小。在重試次數(shù)超過一定次數(shù)后,可能會(huì)中斷 TCP 鏈接。
擁塞處理擁塞處理和流量控制不同,后者是作用于接收方,保證接收方來得及接受數(shù)據(jù)。而前者是作用于網(wǎng)絡(luò),防止過多的數(shù)據(jù)擁塞網(wǎng)絡(luò),避免出現(xiàn)網(wǎng)絡(luò)負(fù)載過大的情況。
擁塞處理包括了四個(gè)算法,分別為:慢開始,擁塞避免,快速重傳,快速恢復(fù)。
慢開始算法慢開始算法,顧名思義,就是在傳輸開始時(shí)將發(fā)送窗口慢慢指數(shù)級擴(kuò)大,從而避免一開始就傳輸大量數(shù)據(jù)導(dǎo)致網(wǎng)絡(luò)擁塞。
慢開始算法步驟具體如下
連接初始設(shè)置擁塞窗口(Congestion Window) 為 1 MSS(一個(gè)分段的最大數(shù)據(jù)量)
每過一個(gè) RTT 就將窗口大小乘二
指數(shù)級增長肯定不能沒有限制的,所以有一個(gè)閾值限制,當(dāng)窗口大小大于閾值時(shí)就會(huì)啟動(dòng)擁塞避免算法。
擁塞避免算法擁塞避免算法相比簡單點(diǎn),每過一個(gè) RTT 窗口大小只加一,這樣能夠避免指數(shù)級增長導(dǎo)致網(wǎng)絡(luò)擁塞,慢慢將大小調(diào)整到最佳值。
在傳輸過程中可能定時(shí)器超時(shí)的情況,這時(shí)候 TCP 會(huì)認(rèn)為網(wǎng)絡(luò)擁塞了,會(huì)馬上進(jìn)行以下步驟:
將閾值設(shè)為當(dāng)前擁塞窗口的一半
將擁塞窗口設(shè)為 1 MSS
啟動(dòng)擁塞避免算法
快速重傳快速重傳一般和快恢復(fù)一起出現(xiàn)。一旦接收端收到的報(bào)文出現(xiàn)失序的情況,接收端只會(huì)回復(fù)最后一個(gè)順序正確的報(bào)文序號(沒有 Sack 的情況下)。如果收到三個(gè)重復(fù)的 ACK,無需等待定時(shí)器超時(shí)再重發(fā)而是啟動(dòng)快速重傳。具體算法分為兩種:
TCP Taho 實(shí)現(xiàn)如下
將閾值設(shè)為當(dāng)前擁塞窗口的一半
將擁塞窗口設(shè)為 1 MSS
重新開始慢開始算法
TCP Reno 實(shí)現(xiàn)如下
擁塞窗口減半
將閾值設(shè)為當(dāng)前擁塞窗口
進(jìn)入快恢復(fù)階段(重發(fā)對端需要的包,一旦收到一個(gè)新的 ACK 答復(fù)就退出該階段)
使用擁塞避免算法
TCP New Ren 改進(jìn)后的快恢復(fù)TCP New Reno 算法改進(jìn)了之前 TCP Reno 算法的缺陷。在之前,快恢復(fù)中只要收到一個(gè)新的 ACK 包,就會(huì)退出快恢復(fù)。
在 TCP New Reno 中,TCP 發(fā)送方先記下三個(gè)重復(fù) ACK 的分段的最大序號。
假如我有一個(gè)分段數(shù)據(jù)是 1 ~ 10 這十個(gè)序號的報(bào)文,其中丟失了序號為 3 和 7 的報(bào)文,那么該分段的最大序號就是 10。發(fā)送端只會(huì)收到 ACK 序號為 3 的應(yīng)答。這時(shí)候重發(fā)序號為 3 的報(bào)文,接收方順利接收并會(huì)發(fā)送 ACK 序號為 7 的應(yīng)答。這時(shí)候 TCP 知道對端是有多個(gè)包未收到,會(huì)繼續(xù)發(fā)送序號為 7 的報(bào)文,接收方順利接收并會(huì)發(fā)送 ACK 序號為 11 的應(yīng)答,這時(shí)發(fā)送端認(rèn)為這個(gè)分段接收端已經(jīng)順利接收,接下來會(huì)退出快恢復(fù)階段。
HTTPHTTP 協(xié)議是個(gè)無狀態(tài)協(xié)議,不會(huì)保存狀態(tài)。
Post 和 Get 的區(qū)別先引入副作用和冪等的概念。
副作用指對服務(wù)器上的資源做改變,搜索是無副作用的,注冊是副作用的。
冪等指發(fā)送 M 和 N 次請求(兩者不相同且都大于 1),服務(wù)器上資源的狀態(tài)一致,比如注冊 10 個(gè)和 11 個(gè)帳號是不冪等的,對文章進(jìn)行更改 10 次和 11 次是冪等的。
在規(guī)范的應(yīng)用場景上說,Get 多用于無副作用,冪等的場景,例如搜索關(guān)鍵字。Post 多用于副作用,不冪等的場景,例如注冊。
在技術(shù)上說:
Get 請求能緩存,Post 不能
Post 相對 Get 安全一點(diǎn)點(diǎn),因?yàn)镚et 請求都包含在 URL 里,且會(huì)被瀏覽器保存歷史紀(jì)錄,Post 不會(huì),但是在抓包的情況下都是一樣的。
Post 可以通過 request body來傳輸比 Get 更多的數(shù)據(jù),Get 沒有這個(gè)技術(shù)
URL有長度限制,會(huì)影響 Get 請求,但是這個(gè)長度限制是瀏覽器規(guī)定的,不是 RFC 規(guī)定的
Post 支持更多的編碼類型且不對數(shù)據(jù)類型限制
常見狀態(tài)碼2XX 成功
200 OK,表示從客戶端發(fā)來的請求在服務(wù)器端被正確處理
204 No content,表示請求成功,但響應(yīng)報(bào)文不含實(shí)體的主體部分
205 Reset Content,表示請求成功,但響應(yīng)報(bào)文不含實(shí)體的主體部分,但是與 204 響應(yīng)不同在于要求請求方重置內(nèi)容
206 Partial Content,進(jìn)行范圍請求
3XX 重定向
301 moved permanently,永久性重定向,表示資源已被分配了新的 URL
302 found,臨時(shí)性重定向,表示資源臨時(shí)被分配了新的 URL
303 see other,表示資源存在著另一個(gè) URL,應(yīng)使用 GET 方法獲取資源
304 not modified,表示服務(wù)器允許訪問資源,但因發(fā)生請求未滿足條件的情況
307 temporary redirect,臨時(shí)重定向,和302含義類似,但是期望客戶端保持請求方法不變向新的地址發(fā)出請求
4XX 客戶端錯(cuò)誤
400 bad request,請求報(bào)文存在語法錯(cuò)誤
401 unauthorized,表示發(fā)送的請求需要有通過 HTTP 認(rèn)證的認(rèn)證信息
403 forbidden,表示對請求資源的訪問被服務(wù)器拒絕
404 not found,表示在服務(wù)器上沒有找到請求的資源
5XX 服務(wù)器錯(cuò)誤
500 internal sever error,表示服務(wù)器端在執(zhí)行請求時(shí)發(fā)生了錯(cuò)誤
501 Not Implemented,表示服務(wù)器不支持當(dāng)前請求所需要的某個(gè)功能
503 service unavailable,表明服務(wù)器暫時(shí)處于超負(fù)載或正在停機(jī)維護(hù),無法處理請求
HTTP 首部通用字段 | 作用 |
---|---|
Cache-Control | 控制緩存的行為 |
Connection | 瀏覽器想要優(yōu)先使用的連接類型,比如 keep-alive |
Date | 創(chuàng)建報(bào)文時(shí)間 |
Pragma | 報(bào)文指令 |
Via | 代理服務(wù)器相關(guān)信息 |
Transfer-Encoding | 傳輸編碼方式 |
Upgrade | 要求客戶端升級協(xié)議 |
Warning | 在內(nèi)容中可能存在錯(cuò)誤 |
請求字段 | 作用 |
---|---|
Accept | 能正確接收的媒體類型 |
Accept-Charset | 能正確接收的字符集 |
Accept-Encoding | 能正確接收的編碼格式列表 |
Accept-Language | 能正確接收的語言列表 |
Expect | 期待服務(wù)端的指定行為 |
From | 請求方郵箱地址 |
Host | 服務(wù)器的域名 |
If-Match | 兩端資源標(biāo)記比較 |
If-Modified-Since | 本地資源未修改返回 304(比較時(shí)間) |
If-None-Match | 本地資源未修改返回 304(比較標(biāo)記) |
User-Agent | 客戶端信息 |
Max-Forwards | 限制可被代理及網(wǎng)關(guān)轉(zhuǎn)發(fā)的次數(shù) |
Proxy-Authorization | 向代理服務(wù)器發(fā)送驗(yàn)證信息 |
Range | 請求某個(gè)內(nèi)容的一部分 |
Referer | 表示瀏覽器所訪問的前一個(gè)頁面 |
TE | 傳輸編碼方式 |
響應(yīng)字段 | 作用 |
---|---|
Accept-Ranges | 是否支持某些種類的范圍 |
Age | 資源在代理緩存中存在的時(shí)間 |
ETag | 資源標(biāo)識 |
Location | 客戶端重定向到某個(gè) URL |
Proxy-Authenticate | 向代理服務(wù)器發(fā)送驗(yàn)證信息 |
Server | 服務(wù)器名字 |
WWW-Authenticate | 獲取資源需要的驗(yàn)證信息 |
實(shí)體字段 | 作用 |
---|---|
Allow | 資源的正確請求方式 |
Content-Encoding | 內(nèi)容的編碼格式 |
Content-Language | 內(nèi)容使用的語言 |
Content-Length | request body 長度 |
Content-Location | 返回?cái)?shù)據(jù)的備用地址 |
Content-MD5 | Base64加密格式的內(nèi)容 MD5檢驗(yàn)值 |
Content-Range | 內(nèi)容的位置范圍 |
Content-Type | 內(nèi)容的媒體類型 |
Expires | 內(nèi)容的過期時(shí)間 |
Last_modified | 內(nèi)容的最后修改時(shí)間 |
PS:緩存相關(guān)已在別的模塊中寫完,你可以 閱讀該小節(jié)
HTTPSHTTPS 還是通過了 HTTP 來傳輸信息,但是信息通過 TLS 協(xié)議進(jìn)行了加密。
TLSTLS 協(xié)議位于傳輸層之上,應(yīng)用層之下。首次進(jìn)行 TLS 協(xié)議傳輸需要兩個(gè) RTT ,接下來可以通過 Session Resumption 減少到一個(gè) RTT。
在 TLS 中使用了兩種加密技術(shù),分別為:對稱加密和非對稱加密。
對稱加密:
對稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密。
非對稱加密:
有公鑰私鑰之分,公鑰所有人都可以知道,可以將數(shù)據(jù)用公鑰加密,但是將數(shù)據(jù)解密必須使用私鑰解密,私鑰只有分發(fā)公鑰的一方才知道。
TLS 握手過程如下圖:
客戶端發(fā)送一個(gè)隨機(jī)值,需要的協(xié)議和加密方式
服務(wù)端收到客戶端的隨機(jī)值,自己也產(chǎn)生一個(gè)隨機(jī)值,并根據(jù)客戶端需求的協(xié)議和加密方式來使用對應(yīng)的方式,發(fā)送自己的證書(如果需要驗(yàn)證客戶端證書需要說明)
客戶端收到服務(wù)端的證書并驗(yàn)證是否有效,驗(yàn)證通過會(huì)再生成一個(gè)隨機(jī)值,通過服務(wù)端證書的公鑰去加密這個(gè)隨機(jī)值并發(fā)送給服務(wù)端,如果服務(wù)端需要驗(yàn)證客戶端證書的話會(huì)附帶證書
服務(wù)端收到加密過的隨機(jī)值并使用私鑰解密獲得第三個(gè)隨機(jī)值,這時(shí)候兩端都擁有了三個(gè)隨機(jī)值,可以通過這三個(gè)隨機(jī)值按照之前約定的加密方式生成密鑰,接下來的通信就可以通過該密鑰來加密解密
通過以上步驟可知,在 TLS 握手階段,兩端使用非對稱加密的方式來通信,但是因?yàn)榉菍ΨQ加密損耗的性能比對稱加密大,所以在正式傳輸數(shù)據(jù)時(shí),兩端使用對稱加密的方式通信。
PS:以上說明的都是 TLS 1.2 協(xié)議的握手情況,在 1.3 協(xié)議中,首次建立連接只需要一個(gè) RTT,后面恢復(fù)連接不需要 RTT 了。
HTTP 2.0HTTP 2.0 相比于 HTTP 1.X,可以說是大幅度提高了 web 的性能。
在 HTTP 1.X 中,為了性能考慮,我們會(huì)引入雪碧圖、將小圖內(nèi)聯(lián)、使用多個(gè)域名等等的方式。這一切都是因?yàn)闉g覽器限制了同一個(gè)域名下的請求數(shù)量,當(dāng)頁面中需要請求很多資源的時(shí)候,隊(duì)頭阻塞(Head of line blocking)會(huì)導(dǎo)致在達(dá)到最大請求數(shù)量時(shí),剩余的資源需要等待其他資源請求完成后才能發(fā)起請求。
你可以通過 該鏈接 感受下 HTTP 2.0 比 HTTP 1.X 到底快了多少。
在 HTTP 1.X 中,因?yàn)殛?duì)頭阻塞的原因,你會(huì)發(fā)現(xiàn)請求是這樣的
在 HTTP 2.0 中,因?yàn)橐肓硕嗦窂?fù)用,你會(huì)發(fā)現(xiàn)請求是這樣的
二進(jìn)制傳輸HTTP 2.0 中所有加強(qiáng)性能的核心點(diǎn)在于此。在之前的 HTTP 版本中,我們是通過文本的方式傳輸數(shù)據(jù)。在 HTTP 2.0 中引入了新的編碼機(jī)制,所有傳輸?shù)臄?shù)據(jù)都會(huì)被分割,并采用二進(jìn)制格式編碼。
多路復(fù)用在 HTTP 2.0 中,有兩個(gè)非常重要的概念,分別是幀(frame)和流(stream)。
幀代表著最小的數(shù)據(jù)單位,每個(gè)幀會(huì)標(biāo)識出該幀屬于哪個(gè)流,流也就是多個(gè)幀組成的數(shù)據(jù)流。
多路復(fù)用,就是在一個(gè) TCP 連接中可以存在多條流。換句話說,也就是可以發(fā)送多個(gè)請求,對端可以通過幀中的標(biāo)識知道屬于哪個(gè)請求。通過這個(gè)技術(shù),可以避免 HTTP 舊版本中的隊(duì)頭阻塞問題,極大的提高傳輸性能。
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ù)端可以在客戶端某個(gè)請求后,主動(dòng)推送其他資源。
可以想象以下情況,某些資源客戶端是一定會(huì)請求的,這時(shí)就可以采取服務(wù)端 push 的技術(shù),提前給客戶端推送必要的資源,這樣就可以相對減少一點(diǎn)延遲時(shí)間。當(dāng)然在瀏覽器兼容的情況下你也可以使用 prefetch 。
QUIC這是一個(gè)谷歌出品的基于 UDP 實(shí)現(xiàn)的同為傳輸層的協(xié)議,目標(biāo)很遠(yuǎn)大,希望替代 TCP 協(xié)議。
該協(xié)議支持多路復(fù)用,雖然 HTTP 2.0 也支持多路復(fù)用,但是下層仍是 TCP,因?yàn)?TCP 的重傳機(jī)制,只要一個(gè)包丟失就得判斷丟失包并且重傳,導(dǎo)致發(fā)生隊(duì)頭阻塞的問題,但是 UDP 沒有這個(gè)機(jī)制
實(shí)現(xiàn)了自己的加密協(xié)議,通過類似 TCP 的 TFO 機(jī)制可以實(shí)現(xiàn) 0-RTT,當(dāng)然 TLS 1.3 已經(jīng)實(shí)現(xiàn)了 0-RTT 了
支持重傳和糾錯(cuò)機(jī)制(向前恢復(fù)),在只丟失一個(gè)包的情況下不需要重傳,使用糾錯(cuò)機(jī)制恢復(fù)丟失的包
糾錯(cuò)機(jī)制:通過異或的方式,算出發(fā)出去的數(shù)據(jù)的異或值并多帶帶發(fā)出一個(gè)包,服務(wù)端在發(fā)現(xiàn)有一個(gè)包丟失的情況下,通過其他數(shù)據(jù)包和異或值包算出丟失包
在丟失兩個(gè)包或以上的情況就使用重傳機(jī)制,因?yàn)樗悴怀鰜砹?/p>
DNSDNS 的作用就是通過域名查詢到具體的 IP。
因?yàn)?IP 存在數(shù)字和英文的組合(IPv6),很不利于人類記憶,所以就出現(xiàn)了域名。你可以把域名看成是某個(gè) IP 的別名,DNS 就是去查詢這個(gè)別名的真正名稱是什么。
在 TCP 握手之前就已經(jīng)進(jìn)行了 DNS 查詢,這個(gè)查詢是操作系統(tǒng)自己做的。當(dāng)你在瀏覽器中想訪問 www.google.com 時(shí),會(huì)進(jìn)行一下操作:
操作系統(tǒng)會(huì)首先在本地緩存中查詢
沒有的話會(huì)去系統(tǒng)配置的 DNS 服務(wù)器中查詢
如果這時(shí)候還沒得話,會(huì)直接去 DNS 根服務(wù)器查詢,這一步查詢會(huì)找出負(fù)責(zé) com 這個(gè)一級域名的服務(wù)器
然后去該服務(wù)器查詢 google 這個(gè)二級域名
接下來三級域名的查詢其實(shí)是我們配置的,你可以給 www 這個(gè)域名配置一個(gè) IP,然后還可以給別的三級域名配置一個(gè) IP
以上介紹的是 DNS 迭代查詢,還有種是遞歸查詢,區(qū)別就是前者是由客戶端去做請求,后者是由系統(tǒng)配置的 DNS 服務(wù)器做請求,得到結(jié)果后將數(shù)據(jù)返回給客戶端。
PS:DNS 是基于 UDP 做的查詢。
從輸入 URL 到頁面加載完成的過程這是一個(gè)很經(jīng)典的面試題,在這題中可以將本文講得內(nèi)容都串聯(lián)起來。
首先做 DNS 查詢,如果這一步做了智能 DNS 解析的話,會(huì)提供訪問速度最快的 IP 地址回來
接下來是 TCP 握手,應(yīng)用層會(huì)下發(fā)數(shù)據(jù)給傳輸層,這里 TCP 協(xié)議會(huì)指明兩端的端口號,然后下發(fā)給網(wǎng)絡(luò)層。網(wǎng)絡(luò)層中的 IP 協(xié)議會(huì)確定 IP 地址,并且指示了數(shù)據(jù)傳輸中如何跳轉(zhuǎn)路由器。然后包會(huì)再被封裝到數(shù)據(jù)鏈路層的數(shù)據(jù)幀結(jié)構(gòu)中,最后就是物理層面的傳輸了
TCP 握手結(jié)束后會(huì)進(jìn)行 TLS 握手,然后就開始正式的傳輸數(shù)據(jù)
數(shù)據(jù)在進(jìn)入服務(wù)端之前,可能還會(huì)先經(jīng)過負(fù)責(zé)負(fù)載均衡的服務(wù)器,它的作用就是將請求合理的分發(fā)到多臺服務(wù)器上,這時(shí)假設(shè)服務(wù)端會(huì)響應(yīng)一個(gè) HTML 文件
首先瀏覽器會(huì)判斷狀態(tài)碼是什么,如果是 200 那就繼續(xù)解析,如果 400 或 500 的話就會(huì)報(bào)錯(cuò),如果 300 的話會(huì)進(jìn)行重定向,這里會(huì)有個(gè)重定向計(jì)數(shù)器,避免過多次的重定向,超過次數(shù)也會(huì)報(bào)錯(cuò)
瀏覽器開始解析文件,如果是 gzip 格式的話會(huì)先解壓一下,然后通過文件的編碼格式知道該如何去解碼文件
文件解碼成功后會(huì)正式開始渲染流程,先會(huì)根據(jù) HTML 構(gòu)建 DOM 樹,有 CSS 的話會(huì)去構(gòu)建 CSSOM 樹。如果遇到 script 標(biāo)簽的話,會(huì)判斷是否存在 async 或者 defer ,前者會(huì)并行進(jìn)行下載并執(zhí)行 JS,后者會(huì)先下載文件,然后等待 HTML 解析完成后順序執(zhí)行,如果以上都沒有,就會(huì)阻塞住渲染流程直到 JS 執(zhí)行完畢。遇到文件下載的會(huì)去下載文件,這里如果使用 HTTP 2.0 協(xié)議的話會(huì)極大的提高多圖的下載效率。
初始的 HTML 被完全加載和解析后會(huì)觸發(fā) DOMContentLoaded 事件
CSSOM 樹和 DOM 樹構(gòu)建完成后會(huì)開始生成 Render 樹,這一步就是確定頁面元素的布局、樣式等等諸多方面的東西
在生成 Render 樹的過程中,瀏覽器就開始調(diào)用 GPU 繪制,合成圖層,將內(nèi)容顯示在屏幕上了
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/108888.html
摘要:這時(shí)候超過定時(shí)器設(shè)定的時(shí)間就會(huì)再次發(fā)送丟包的數(shù)據(jù)直到對端響應(yīng),所以需要每次都備份發(fā)送的數(shù)據(jù)。 UDP 面向報(bào)文 UDP 是一個(gè)面向報(bào)文(報(bào)文可以理解為一段段的數(shù)據(jù))的協(xié)議。意思就是 UDP 只是報(bào)文的搬運(yùn)工,不會(huì)對報(bào)文進(jìn)行任何拆分和拼接操作。 具體來說 在發(fā)送端,應(yīng)用層將數(shù)據(jù)傳遞給傳輸層的 UDP 協(xié)議,UDP 只會(huì)給數(shù)據(jù)增加一個(gè) UDP 頭標(biāo)識下是 UDP 協(xié)議,然后就傳遞給網(wǎng)絡(luò)層...
摘要:代碼實(shí)現(xiàn)代碼實(shí)現(xiàn)接下來思考一個(gè)熔斷器如何實(shí)現(xiàn)。同時(shí)熔斷器的狀態(tài)也需要依靠指標(biāo)統(tǒng)計(jì)來實(shí)現(xiàn)可觀測性,我們實(shí)現(xiàn)任何系統(tǒng)第一步需要考慮就是可觀測性,不然系統(tǒng)就是一個(gè)黑盒??赡苁?,熔斷器需要實(shí)時(shí)收集此數(shù)據(jù)。熔斷方法,自動(dòng)上報(bào)執(zhí)行結(jié)果自動(dòng)擋。。。為什么需要熔斷微服務(wù)集群中,每個(gè)應(yīng)用基本都會(huì)依賴一定數(shù)量的外部服務(wù)。有可能隨時(shí)都會(huì)遇到網(wǎng)絡(luò)連接緩慢,超時(shí),依賴服務(wù)過載,服務(wù)不可用的情況,在高并發(fā)場景下如果此時(shí)...
摘要:端口,協(xié)議,域名,有一者不同就會(huì)出現(xiàn)跨域的問題。解決跨域的方式怎樣解決跨域所謂的解決跨域問題就是前端在合適的時(shí)期動(dòng)態(tài)添加一個(gè)標(biāo)簽,請求后端給的接口帶上一個(gè)回調(diào)函數(shù)。因?yàn)闃?biāo)簽不受瀏覽器同源策略的限制。 跨域 為什么會(huì)出現(xiàn)跨域? 因?yàn)闉g覽器有同源策略的限制,同源策略是瀏覽器最核心最基礎(chǔ)的安全策略。 端口,協(xié)議,域名,有一者不同就會(huì)出現(xiàn)跨域的問題。 解決跨域的方式 JSONP CORS...
摘要:決定了注冊的事件是捕獲事件還是冒泡事件。瀏覽器會(huì)自動(dòng)進(jìn)行通信,實(shí)現(xiàn)通信的關(guān)鍵是后端。該方式只能用于二級域名相同的情況下,比如和適用于該方式。中的中的和瀏覽器中的不相同。 事件機(jī)制 事件觸發(fā)三階段 事件觸發(fā)有三個(gè)階段 window 往事件觸發(fā)處傳播,遇到注冊的捕獲事件會(huì)觸發(fā) 傳播到事件觸發(fā)處時(shí)觸發(fā)注冊的事件 從事件觸發(fā)處往 window 傳播,遇到注冊的冒泡事件會(huì)觸發(fā) 事件觸發(fā)一般...
閱讀 1492·2021-11-25 09:43
閱讀 2635·2021-09-24 10:30
閱讀 3691·2021-09-06 15:02
閱讀 3630·2019-08-30 15:55
閱讀 3321·2019-08-30 15:53
閱讀 1722·2019-08-30 15:52
閱讀 2164·2019-08-30 14:21
閱讀 2039·2019-08-30 13:55