瀏覽器輸入「xxxxhub」的背后.....

今天就以 Web 頁(yè)面的請(qǐng)求歷程為例,來(lái)和你聊聊計(jì)算機(jī)網(wǎng)絡(luò)中這些協(xié)議是怎樣工作的、數(shù)據(jù)包是怎么收發(fā)的,從輸入 URL 、敲擊回車(chē)到最終完成頁(yè)面呈現(xiàn)在你面前的這個(gè)過(guò)程。
首先,我打開(kāi)了 Web Browser ,然后在 Google 瀏覽器 URL 地址欄中輸入了 maps.google.com。

然后 ……
查找 DNS 緩存
瀏覽器在這個(gè)階段會(huì)檢查四個(gè)地方是否存在緩存,第一個(gè)地方是瀏覽器緩存,這個(gè)緩存就是 DNS 記錄。
瀏覽器會(huì)為你訪問(wèn)過(guò)的網(wǎng)站在固定期限內(nèi)維護(hù) DNS 記錄。因此,它是第一個(gè)運(yùn)行 DNS 查詢(xún)的地方。瀏覽器首先會(huì)檢查這個(gè)網(wǎng)址在瀏覽器中是否有一條對(duì)應(yīng)的 DNS 記錄,用來(lái)找到目標(biāo)網(wǎng)址的 IP 地址。
我是 chrome 瀏覽器,所以在 mac 中,無(wú)法使用 chrome://net-internals/#dns 找到對(duì)應(yīng)的 IP 地址,在 windows 中是可以找到的。
那么 mac 怎么查詢(xún) DNS 記錄呢?你可以使用
nslookup命令來(lái)查找,但這不是我們討論的重點(diǎn)。
DNS(Domain Name System) 是一個(gè)分布式的數(shù)據(jù)庫(kù),它用于維護(hù)網(wǎng)址 URL 到其 IP 地址的映射關(guān)系。在互聯(lián)網(wǎng)中,IP 地址是計(jì)算機(jī)所能夠理解的一種地址,而 DNS 的這種別名地址是我們?nèi)祟?lèi)能夠理解和記憶的地址,DNS 就負(fù)責(zé)把人類(lèi)記憶的地址映射成計(jì)算機(jī)能夠理解的地址,每個(gè) URL 都有唯一的 IP 地址進(jìn)行對(duì)應(yīng)。
舉個(gè)例子,google 的官網(wǎng)是 www.google.com ,而 google 的 ip 地址是 216.58.200.228 ,這兩個(gè)地址你在 URL 上輸入哪個(gè)都能訪問(wèn),但是 IP 地址不好記憶,而 google.com 簡(jiǎn)單明了。DNS 就相當(dāng)于是我們幾年前使用的家庭電話薄,比如你想給 cxuan 打電話,你有可能記不住 cxuan 的電話號(hào)碼,此時(shí)你需要查詢(xún)電話薄來(lái)找到 cxuan 的電話號(hào)碼。
瀏覽器第二個(gè)需要檢查的地方就是操作系統(tǒng)緩存。如果 DNS 記錄不在瀏覽器緩存中,那么瀏覽器將對(duì)操作系統(tǒng)發(fā)起系統(tǒng)調(diào)用,Windows 下就是 getHostName。
在 Linux 和大部分 UNIX 系統(tǒng)上,除非安裝了
nscd,否則操作系統(tǒng)可能沒(méi)有 DNS 緩存。nscd 是 Linux 系統(tǒng)上的一種名稱(chēng)服務(wù)緩存程序。
瀏覽器第三個(gè)需要檢查的地方是路由器緩存,如果 DNS 記錄不在自己電腦上的話,瀏覽器就會(huì)和與之相連的路由器共同維護(hù) DNS 記錄。
如果與之相連的路由器也沒(méi)有 DNS 記錄的話,瀏覽器就會(huì)檢查 ISP 中是否有緩存。ISP 緩存就是你本地通信服務(wù)商的緩存,因?yàn)?ISP 維護(hù)著自己的 DNS 服務(wù)器,它緩存 DNS 記錄的本質(zhì)也是為了降低請(qǐng)求時(shí)間,達(dá)到快速響應(yīng)的效果。一旦你訪問(wèn)過(guò)某些網(wǎng)站,你的 ISP 可能就會(huì)緩存這些頁(yè)面,以便下次快速訪問(wèn)。對(duì)于經(jīng)??葱‰娪暗哪闶欠窀械秸痼@呢?如果家里還安裝了一個(gè)可以聯(lián)網(wǎng)的攝像頭的話,那就有點(diǎn)嗨皮了。
你肯定比較困惑為什么第一步瀏覽器需要檢查這么多緩存,你可能會(huì)感到不舒服,因?yàn)榫彺婵赡軙?huì)透露我們的隱私,但是這些緩存在調(diào)節(jié)網(wǎng)絡(luò)流量和縮短數(shù)據(jù)傳輸時(shí)間等方面至關(guān)重要。
所以,上面涉及到 DNS 緩存的查詢(xún)過(guò)程如下。

如果上面四個(gè)步驟中都不存在 DNS 記錄,那么就表示不存在 DNS 緩存,這個(gè)時(shí)候就需要發(fā)起 DNS 查詢(xún),以查找目標(biāo)網(wǎng)址(本示例中是 maps.google.com)的 IP 地址。
發(fā)起 DNS 查詢(xún)
如上所述,如果想要使我的計(jì)算機(jī)和 maps.google.com 建立連接并進(jìn)行通信的話,我需要知道 maps.google.com 的 IP 地址,由于 DNS 的設(shè)計(jì)原因,本地 DNS 可能無(wú)法給我提供正確的 IP 地址,那么它就需要在互聯(lián)網(wǎng)上搜索多個(gè) DNS 服務(wù)器,來(lái)找到網(wǎng)站的正確 IP 地址。
這里有個(gè)疑問(wèn),為什么我需要搜索多個(gè) DNS 服務(wù)器的來(lái)找到網(wǎng)站的 IP 地址呢?一臺(tái)服務(wù)器不行嗎?
因?yàn)?DNS 是分布式域名服務(wù)器,每臺(tái)服務(wù)器只維護(hù)一部分 IP 地址到網(wǎng)絡(luò)地址的映射,沒(méi)有任何一臺(tái)服務(wù)器能夠維持全部的映射關(guān)系。
在 DNS 的早期設(shè)計(jì)中只有一臺(tái) DNS 服務(wù)器。這臺(tái)服務(wù)器會(huì)包含所有的 DNS 映射。這是一種集中式的設(shè)計(jì),這種設(shè)計(jì)并不適用于當(dāng)今的互聯(lián)網(wǎng),因?yàn)榛ヂ?lián)網(wǎng)有著數(shù)量巨大并且持續(xù)增長(zhǎng)的主機(jī),這種集中式的設(shè)計(jì)會(huì)存在以下幾個(gè)問(wèn)題
單點(diǎn)故障(a single point of failure),如果 DNS 服務(wù)器崩潰,那么整個(gè)網(wǎng)絡(luò)隨之癱瘓。通信容量(traaffic volume),單個(gè) DNS 服務(wù)器不得不處理所有的 DNS 查詢(xún),這種查詢(xún)級(jí)別可能是上百萬(wàn)上千萬(wàn)級(jí),一臺(tái)服務(wù)器很難滿足。遠(yuǎn)距離集中式數(shù)據(jù)庫(kù)(distant centralized database),單個(gè) DNS 服務(wù)器不可能鄰近所有的用戶,假設(shè)在美國(guó)的 DNS 服務(wù)器不可能臨近讓澳大利亞的查詢(xún)使用,其中查詢(xún)請(qǐng)求勢(shì)必會(huì)經(jīng)過(guò)低速和擁堵的鏈路,造成嚴(yán)重的時(shí)延。維護(hù)(maintenance),維護(hù)成本巨大,而且還需要頻繁更新。
所以在當(dāng)今網(wǎng)絡(luò)情況下 DNS 不可能集中式設(shè)計(jì),因?yàn)樗耆珱](méi)有可擴(kuò)展能力,所以采用分布式設(shè)計(jì),這種設(shè)計(jì)的特點(diǎn)如下
分布式、層次數(shù)據(jù)庫(kù)。
首先分布式設(shè)計(jì)首先解決的問(wèn)題就是 DNS 服務(wù)器的擴(kuò)展性問(wèn)題,因此 DNS 使用了大量的 DNS 服務(wù)器,它們的組織模式一般是層次方式,并且分布在全世界范圍內(nèi)。沒(méi)有一臺(tái) DNS 服務(wù)器能夠擁有因特網(wǎng)上所有主機(jī)的映射。相反,這些映射分布在所有的 DNS 服務(wù)器上。
大致來(lái)說(shuō)有三種 DNS 服務(wù)器:根 DNS 服務(wù)器、 頂級(jí)域(Top-Level Domain, TLD) DNS 服務(wù)器 和 權(quán)威 DNS 服務(wù)器 。這些服務(wù)器的層次模型如下圖所示


根 DNS 服務(wù)器,有 400 多個(gè)根域名服務(wù)器遍及全世界,這些根域名服務(wù)器由 13 個(gè)不同的組織管理。根域名服務(wù)器的清單和組織機(jī)構(gòu)可以在 https://root-servers.org/ 中找到,根域名服務(wù)器提供 TLD 服務(wù)器的 IP 地址。頂級(jí)域 DNS 服務(wù)器,對(duì)于每個(gè)頂級(jí)域名比如 com、org、net、edu 和 gov 和所有的國(guó)家級(jí)域名 uk、fr、ca 和 jp 都有 TLD 服務(wù)器或服務(wù)器集群。所有的頂級(jí)域列表參見(jiàn) https://tld-list.com/ 。TDL 服務(wù)器提供了權(quán)威 DNS 服務(wù)器的 IP 地址。權(quán)威 DNS 服務(wù)器,在因特網(wǎng)上具有公共可訪問(wèn)的主機(jī),如 Web 服務(wù)器和郵件服務(wù)器,這些主機(jī)的組織機(jī)構(gòu)必須提供可供訪問(wèn)的 DNS 記錄,這些記錄將這些主機(jī)的名字映射為 IP 地址。一個(gè)組織機(jī)構(gòu)的權(quán)威 DNS 服務(wù)器收藏了這些 DNS 記錄。
在了解了 DNS 服務(wù)器的設(shè)計(jì)理念之后,我們回到 DNS 查找的步驟上來(lái),DNS 的查詢(xún)方式主要分為三種
DNS 查找中會(huì)出現(xiàn)三種類(lèi)型的查詢(xún)。通過(guò)組合使用這些查詢(xún),優(yōu)化的 DNS 解析過(guò)程可縮短傳輸距離。在理想情況下,可以使用緩存的記錄數(shù)據(jù),從而使 DNS 域名服務(wù)器能夠直接使用非遞歸查詢(xún)。
遞歸查詢(xún):在遞歸查詢(xún)中,DNS 客戶端要求 DNS 服務(wù)器(一般為 DNS 遞歸解析器)將使用所請(qǐng)求的資源記錄響應(yīng)客戶端,或者如果解析器無(wú)法找到該記錄,則返回錯(cuò)誤消息。

迭代查詢(xún):在迭代查詢(xún)中,如果所查詢(xún)的 DNS 服務(wù)器與查詢(xún)名稱(chēng)不匹配,則其將返回對(duì)較低級(jí)別域名空間具有權(quán)威性的 DNS 服務(wù)器的引用。然后,DNS 客戶端將對(duì)引用地址進(jìn)行查詢(xún)。此過(guò)程繼續(xù)使用查詢(xún)鏈中的其他 DNS 服務(wù)器,直至發(fā)生錯(cuò)誤或超時(shí)為止。

非遞歸查詢(xún):當(dāng) DNS 解析器客戶端查詢(xún) DNS 服務(wù)器以獲取其有權(quán)訪問(wèn)的記錄時(shí)通常會(huì)進(jìn)行此查詢(xún),因?yàn)槠鋵?duì)該記錄具有權(quán)威性,或者該記錄存在于其緩存內(nèi)。DNS 服務(wù)器通常會(huì)緩存 DNS 記錄,查詢(xún)到來(lái)后能夠直接返回緩存結(jié)果,以防止更多帶寬消耗和上游服務(wù)器上的負(fù)載。
上面負(fù)責(zé)開(kāi)始 DNS 查找的介質(zhì)就是 DNS 解析器,它一般是 ISP 維護(hù)的 DNS 服務(wù)器,它的主要職責(zé)就是通過(guò)向網(wǎng)絡(luò)中其他 DNS 服務(wù)器詢(xún)問(wèn)正確的 IP 地址。
所以對(duì)于 maps.google.com 這個(gè)域名來(lái)說(shuō),如果 ISP 維護(hù)的服務(wù)器沒(méi)有 DNS 緩存記錄,它就會(huì)向 DNS 根服務(wù)器地址發(fā)起查詢(xún),根名稱(chēng)服務(wù)器會(huì)將其重定向到 .com 頂級(jí)域名服務(wù)器。.com 頂級(jí)域名服務(wù)器會(huì)將其重定向到google.com 權(quán)威服務(wù)器。google.com 名稱(chēng)服務(wù)器將在其 DNS 記錄中找到 maps.google.com 匹配的 IP 地址,并將其返回給您的 DNS 解析器,然后將其發(fā)送回你的瀏覽器。
這里值得注意的是,DNS 查詢(xún)報(bào)文會(huì)經(jīng)過(guò)許多路由器和設(shè)備才會(huì)達(dá)到根域名等服務(wù)器,每經(jīng)過(guò)一個(gè)設(shè)備或者路由器都會(huì)使用路由表 來(lái)確定哪種路徑是數(shù)據(jù)包達(dá)到目的地最快的選擇。這里面涉及到路由選擇算法,如果小伙伴們想要了解路由選擇算法,可以看看這篇文章 https://www.cisco.com/c/en/us/support/docs/ip/border-gateway-protocol-bgp/13753-25.html#anc3
ARP 請(qǐng)求
我看了很多篇文章都沒(méi)有提到這一點(diǎn),那就是 ARP 請(qǐng)求的這個(gè)過(guò)程。
什么時(shí)候需要發(fā)送 ARP 請(qǐng)求呢?
這里其實(shí)有個(gè)前提條件
如果 DNS 服務(wù)器和我們的主機(jī)在同一個(gè)子網(wǎng)內(nèi),系統(tǒng)會(huì)按照下面的 ARP 過(guò)程對(duì) DNS 服務(wù)器進(jìn)行 ARP 查詢(xún)
如果 DNS 服務(wù)器和我們的主機(jī)在不同的子網(wǎng),系統(tǒng)會(huì)按照下面的 ARP 過(guò)程對(duì)默認(rèn)網(wǎng)關(guān)進(jìn)行查詢(xún)
ARP 協(xié)議的全稱(chēng)是 Address Resolution Protocol(地址解析協(xié)議),它是一個(gè)通過(guò)用于實(shí)現(xiàn)從 IP 地址到 MAC 地址的映射,即詢(xún)問(wèn)目標(biāo) IP 對(duì)應(yīng)的 MAC 地址 的一種協(xié)議。
簡(jiǎn)而言之,ARP 就是一種解決地址問(wèn)題的協(xié)議,它以 IP 地址為線索,定位下一個(gè)應(yīng)該接收數(shù)據(jù)分包的主機(jī) MAC 地址。如果目標(biāo)主機(jī)不在同一個(gè)鏈路上,那么會(huì)查找下一跳路由器的 MAC 地址。
關(guān)于為什么有了 IP 地址,還要有 MAC 地址概述可以參看知乎這個(gè)回答 https://www.zhihu.com/question/21546408
ARP 的大致工作流程如下
假設(shè) A 和 B 位于同一鏈路,不需要經(jīng)過(guò)路由器的轉(zhuǎn)換,主機(jī) A 向主機(jī) B 發(fā)送一個(gè) IP 分組,主機(jī) A 的地址是 192.168.1.2 ,主機(jī) B 的地址是 192.168.1.3,它們都不知道對(duì)方的 MAC 地址是啥,主機(jī) C 和 主機(jī) D 是同一鏈路的其他主機(jī)。

主機(jī) A 想要獲取主機(jī) B 的 MAC 地址,通過(guò)主機(jī) A 會(huì)通過(guò)廣播 的方式向以太網(wǎng)上的所有主機(jī)發(fā)送一個(gè) ARP 請(qǐng)求包,這個(gè) ARP 請(qǐng)求包中包含了主機(jī) A 想要知道的主機(jī) B 的 IP 地址的 MAC 地址。

主機(jī) A 發(fā)送的 ARP 請(qǐng)求包會(huì)被同一鏈路上的所有主機(jī)/路由器接收并進(jìn)行解析。每個(gè)主機(jī)/路由器都會(huì)檢查 ARP 請(qǐng)求包中的信息,如果 ARP 請(qǐng)求包中的目標(biāo) IP 地址 和自己的相同,就會(huì)將自己主機(jī)的 MAC 地址寫(xiě)入響應(yīng)包返回主機(jī) A

由此,可以通過(guò) ARP 從 IP 地址獲取 MAC 地址,實(shí)現(xiàn)同一鏈路內(nèi)的通信。
所以,要想發(fā)送 ARP 廣播,我們需要有一個(gè)目標(biāo) IP 地址,同時(shí)還需要知道用于發(fā)送 ARP 廣播的接口的 MAC 地址。
這里會(huì)涉及到 ARP 緩存的概念。
現(xiàn)在你知道了發(fā)送一次 IP 分組前通過(guò)發(fā)送一次 ARP 請(qǐng)求就能夠確定 MAC 地址。那么是不是每發(fā)送一次都得經(jīng)過(guò)廣播 -> 封裝 ARP 響應(yīng) -> 返回給主機(jī)這一系列流程呢?
想想看,瀏覽器是如何做的?瀏覽器內(nèi)置了緩存能夠緩存你最近經(jīng)常使用的地址,那么 ARP 也是一樣的。ARP 高效運(yùn)行的關(guān)鍵就是維護(hù)每個(gè)主機(jī)和路由器上的 ARP 緩存(或表)。這個(gè)緩存維護(hù)著每個(gè) IP 到 MAC 地址的映射關(guān)系。通過(guò)把第一次 ARP 獲取到的 MAC 地址作為 IP 對(duì) MAC 的映射關(guān)系到一個(gè) ARP 緩存表中,下一次再向這個(gè)地址發(fā)送數(shù)據(jù)報(bào)時(shí)就不再需要重新發(fā)送 ARP 請(qǐng)求了,而是直接使用這個(gè)緩存表中的 MAC 地址進(jìn)行數(shù)據(jù)報(bào)的發(fā)送。每發(fā)送一次 ARP 請(qǐng)求,緩存表中對(duì)應(yīng)的映射關(guān)系都會(huì)被清除。
通過(guò) ARP 緩存,降低了網(wǎng)絡(luò)流量的使用,在一定程度上防止了 ARP 的大量廣播。

一般來(lái)說(shuō),發(fā)送過(guò)一次 ARP 請(qǐng)求后,再次發(fā)送相同請(qǐng)求的幾率比較大,因此使用 ARP 緩存能夠減少 ARP 包的發(fā)送,除此之外,不僅僅 ARP 請(qǐng)求的發(fā)送方能夠緩存 ARP 接收方的 MAC 地址,接收方也能夠緩存 ARP 請(qǐng)求方的 IP 和 MAC 地址,如下所示

不過(guò),MAC 地址的緩存有一定期限,超過(guò)這個(gè)期限后,緩存的內(nèi)容會(huì)被清除。
所以,瀏覽器會(huì)首先查詢(xún) ARP 緩存,如果緩存命中,我們返回結(jié)果:目標(biāo) IP = MAC。
如果緩存沒(méi)有命中:
查看路由表,看看目標(biāo) IP 地址是不是在本地路由表中的某個(gè)子網(wǎng)內(nèi)。是的話,使用跟那個(gè)子網(wǎng)相連的接口,否則使用與默認(rèn)網(wǎng)關(guān)相連的接口。
查詢(xún)選擇的網(wǎng)絡(luò)接口的 MAC 地址
我們發(fā)送一個(gè)數(shù)據(jù)鏈路層的 ARP 請(qǐng)求:

根據(jù)連接主機(jī)和路由器的硬件類(lèi)型不同,可以分為以下幾種情況:
直連:
如果我們和路由器是直接連接的,路由器會(huì)返回一個(gè)
ARP Reply(見(jiàn)下面)。
集線器:
如果我們連接到一個(gè)集線器,集線器會(huì)把 ARP 請(qǐng)求向所有其它端口廣播,如果路由器也連接在其中,它會(huì)返回一個(gè)
ARP Reply。
交換機(jī):
如果我們連接到了一個(gè)交換機(jī),交換機(jī)會(huì)檢查本地 CAM/MAC 表,看看哪個(gè)端口有我們要找的那個(gè) MAC 地址,如果沒(méi)有找到,交換機(jī)會(huì)向所有其它端口廣播這個(gè) ARP 請(qǐng)求。
如果交換機(jī)的 MAC/CAM 表中有對(duì)應(yīng)的條目,交換機(jī)會(huì)向有我們想要查詢(xún)的 MAC 地址的那個(gè)端口發(fā)送 ARP 請(qǐng)求
如果路由器也
連接在其中,它會(huì)返回一個(gè)ARP Reply
ARP Reply:

現(xiàn)在我們有了 DNS 服務(wù)器或者默認(rèn)網(wǎng)關(guān)的 IP 地址,我們可以繼續(xù) DNS 請(qǐng)求了:
使用 53 端口向 DNS 服務(wù)器發(fā)送 UDP 請(qǐng)求包,如果響應(yīng)包太大,會(huì)使用 TCP 協(xié)議
如果本地/ISP DNS 服務(wù)器沒(méi)有找到結(jié)果,它會(huì)發(fā)送一個(gè)遞歸查詢(xún)請(qǐng)求,一層一層向高層 DNS 服務(wù)器做查詢(xún),直到查詢(xún)到起始授權(quán)機(jī)構(gòu),如果找到會(huì)把結(jié)果返回。
(上述均來(lái)自:https://github.com/skyline75489/what-happens-when-zh_CN#dns)
封裝 TCP 數(shù)據(jù)包
瀏覽器得到目標(biāo)服務(wù)器的 IP 地址后,根據(jù) URL 中的端口可以知道端口號(hào) (http 協(xié)議默認(rèn)端口號(hào)是 80, https 默認(rèn)端口號(hào)是 443),會(huì)準(zhǔn)備 TCP 數(shù)據(jù)包。數(shù)據(jù)包的封裝會(huì)經(jīng)過(guò)下面的層層處理,數(shù)據(jù)到達(dá)目標(biāo)主機(jī)后,目標(biāo)主機(jī)會(huì)解析數(shù)據(jù)包,完整的請(qǐng)求和解析過(guò)程如下。

瀏覽器與目標(biāo)服務(wù)器建立 TCP 連接
在經(jīng)過(guò)上述 DNS 和 ARP 查找流程后,瀏覽器就會(huì)收到一個(gè)目標(biāo)服務(wù)器的 IP 和 MAC地址,然后瀏覽器將會(huì)和目標(biāo)服務(wù)器建立連接來(lái)傳輸信息。這里可以使用很多種 Internet 協(xié)議,但是 HTTP 協(xié)議建立連接所使用的運(yùn)輸層協(xié)議是 TCP 協(xié)議。所以這一步驟是瀏覽器與目標(biāo)服務(wù)器建立 TCP 連接的過(guò)程。
TCP 的連接建立需要經(jīng)過(guò) TCP/IP 的三次握手,三次握手的過(guò)程其實(shí)就是瀏覽器和服務(wù)器交換 SYN 同步和 ACK 確認(rèn)消息的過(guò)程。
假設(shè)圖中左端是客戶端主機(jī),右端是服務(wù)端主機(jī),一開(kāi)始,兩端都處于CLOSED(關(guān)閉)狀態(tài)。

服務(wù)端進(jìn)程準(zhǔn)備好接收來(lái)自外部的 TCP 連接。然后服務(wù)端進(jìn)程處于
LISTEN狀態(tài),等待客戶端連接請(qǐng)求。客戶端向服務(wù)器發(fā)出連接請(qǐng)求,請(qǐng)求中首部同步位 SYN = 1,同時(shí)選擇一個(gè)初始序號(hào) sequence ,簡(jiǎn)寫(xiě) seq = x。SYN 報(bào)文段不允許攜帶數(shù)據(jù),只消耗一個(gè)序號(hào)。此時(shí),客戶端進(jìn)入
SYN-SEND狀態(tài)。服務(wù)器收到客戶端連接后,,需要確認(rèn)客戶端的報(bào)文段。在確認(rèn)報(bào)文段中,把 SYN 和 ACK 位都置為 1 。確認(rèn)號(hào)是 ack = x + 1,同時(shí)也為自己選擇一個(gè)初始序號(hào) seq = y。請(qǐng)注意,這個(gè)報(bào)文段也不能攜帶數(shù)據(jù),但同樣要消耗掉一個(gè)序號(hào)。此時(shí),TCP 服務(wù)器進(jìn)入
SYN-RECEIVED(同步收到)狀態(tài)。客戶端在收到服務(wù)器發(fā)出的響應(yīng)后,還需要給出確認(rèn)連接。確認(rèn)連接中的 ACK 置為 1 ,序號(hào)為 seq = x + 1,確認(rèn)號(hào)為 ack = y + 1。TCP 規(guī)定,這個(gè)報(bào)文段可以攜帶數(shù)據(jù)也可以不攜帶數(shù)據(jù),如果不攜帶數(shù)據(jù),那么下一個(gè)數(shù)據(jù)報(bào)文段的序號(hào)仍是 seq = x + 1。這時(shí),客戶端進(jìn)入
ESTABLISHED (已連接)狀態(tài)服務(wù)器收到客戶的確認(rèn)后,也進(jìn)入
ESTABLISHED狀態(tài)。
這樣三次握手建立連接的階段就完成了,雙方可以直接通信了。
瀏覽器發(fā)送 HTTP 請(qǐng)求到 web 服務(wù)器
一旦 TCP 連接建立完成后,就開(kāi)始直接傳輸數(shù)據(jù)辦正事了!此時(shí)瀏覽器會(huì)發(fā)送 GET 請(qǐng)求,要求目標(biāo)服務(wù)器提供 maps.google.com 的網(wǎng)頁(yè),如果你填寫(xiě)的是表單,則發(fā)起的是 POST 請(qǐng)求,在 HTTP 中,GET 請(qǐng)求和 POST 請(qǐng)求是最常見(jiàn)的兩種請(qǐng)求,基本上占據(jù)了所有 HTTP 請(qǐng)求的九成以上。
除了請(qǐng)求類(lèi)型外,HTTP 請(qǐng)求還包含很多很多信息,最常見(jiàn)的有 Host、Connection 、User-agent、Accept-language 等

首先 Host 表示的是對(duì)象所在的主機(jī)。Connection: close 表示的是瀏覽器需要告訴服務(wù)器使用的是非持久連接。它要求服務(wù)器在發(fā)送完響應(yīng)的對(duì)象后就關(guān)閉連接。User-agent: 這是請(qǐng)求頭用來(lái)告訴 Web 服務(wù)器,瀏覽器使用的類(lèi)型是 Mozilla/5.0,即 Firefox 瀏覽器。Accept-language 告訴 Web 服務(wù)器,瀏覽器想要得到對(duì)象的法語(yǔ)版本,前提是服務(wù)器需要支持法語(yǔ)類(lèi)型,否則將會(huì)發(fā)送服務(wù)器的默認(rèn)版本。下面我們針對(duì)主要的實(shí)體字段進(jìn)行介紹(具體的可以參考 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers MDN 官網(wǎng)學(xué)習(xí))
HTTP 的請(qǐng)求標(biāo)頭分為四種: 通用標(biāo)頭、請(qǐng)求標(biāo)頭、響應(yīng)標(biāo)頭 和 實(shí)體標(biāo)頭。
服務(wù)器處理請(qǐng)求并發(fā)回一個(gè)響應(yīng)
這個(gè)服務(wù)器包含一個(gè) Web 服務(wù)器,也就是 Apache 服務(wù)器,服務(wù)器會(huì)從瀏覽器接收請(qǐng)求并將其傳遞給請(qǐng)求處理程序并生成響應(yīng)。
請(qǐng)求處理程序也是一個(gè)程序,它一般是用 .net 、php、ruby 等語(yǔ)言編寫(xiě),用于讀取請(qǐng)求,檢查請(qǐng)求內(nèi)容,cookie,必要時(shí)更新服務(wù)器上的信息的這么一個(gè)程序。它會(huì)以特定的格式比如 JSON、XML、HTML 組合響應(yīng)。
服務(wù)器發(fā)送回一個(gè) HTTP 響應(yīng)
服務(wù)器響應(yīng)包含你請(qǐng)求的網(wǎng)頁(yè)以及狀態(tài)代碼,壓縮類(lèi)型(Content-Encoding),如何緩存頁(yè)面(Cache-Control),要設(shè)置的 cookie,隱私信息等。
比如下面就是一個(gè)響應(yīng)體

瀏覽器顯示 HTML 的相關(guān)內(nèi)容
瀏覽器會(huì)分階段顯示 HTML 內(nèi)容。首先,它將渲染裸露的 HTML 骨架。然后它將檢查 HTML 標(biāo)記并發(fā)送 GET 請(qǐng)求以獲取網(wǎng)頁(yè)上的其他元素,例如圖像,CSS 樣式表,JavaScript 文件等。這些靜態(tài)文件由瀏覽器緩存,因此你再次訪問(wèn)該頁(yè)面時(shí),不用重新再請(qǐng)求一次。最后,您會(huì)看到 maps.google.com 顯示的內(nèi)容出現(xiàn)在你的瀏覽器中。
