面試 | 當(dāng)你輸入U(xiǎn)RL到頁面渲染出來中間發(fā)生了什么?
新的一篇,最近在學(xué)習(xí) go 語言,現(xiàn)在很多大廠都在用 go 重構(gòu)產(chǎn)品,這語言未來會比較火,雙修 go ,以后也會更新一些 go語言方面的文章。
今天來聊一聊這道面試題:當(dāng)你輸入網(wǎng)站到頁面渲染出來中間包的交互過程
流程DNS 域名解析
將域名轉(zhuǎn)換為對應(yīng)IP地址。
TCP連接
通過 IP 地址找到對應(yīng)服務(wù)器,三次握手建立 TCP 連接。
發(fā)送 HTTP 請求
客戶端封裝發(fā)送 HTTP 請求包(應(yīng)用層-網(wǎng)絡(luò)層-傳輸層-數(shù)據(jù)鏈路層)
服務(wù)器響應(yīng)請求返回 HTTP報(bào)文
服務(wù)器處理 http請求包(數(shù)據(jù)鏈路層-傳輸層-網(wǎng)絡(luò)層-應(yīng)用層),構(gòu)建響應(yīng)
瀏覽器解析渲染頁面
客戶端收到響應(yīng)包,解析 HTML,構(gòu)建 render樹,根據(jù)render 樹節(jié)點(diǎn)和 CSS的對應(yīng)關(guān)系,進(jìn)行布局,繪制頁面
TCP斷開連接
四次揮手?jǐn)嚅_連接。
你可能記得很多網(wǎng)址,但應(yīng)該不會記得多少網(wǎng)站IP地址,DNS服務(wù)器就是幫助幫你記住網(wǎng)址對應(yīng)的IP。
查詢方式:遞歸查詢,迭代查詢
從瀏覽器緩存 --> 本地 host 文件 -->本地 DNS 解析器緩存 -->本地 DNS 服務(wù)器,這個過程中,任何一步找到了都會結(jié)束查找流程。
如果 DNS 服務(wù)器也無法查詢到,則進(jìn)行根域名服務(wù)器 -->頂級域名服務(wù)器 --> 權(quán)威域名服務(wù)器的迭代查詢

DNS獲取到請求域名服務(wù)器的IP地址之后,與服務(wù)器三次握手建立 TCP 連接

第一次握手:客戶端將標(biāo)志位 SYN 位為 1,seq為 X(X的值為 1-1234567 的隨機(jī)值)的連接請求報(bào)文發(fā)出,進(jìn)入SYN_SEND 狀態(tài),等待服務(wù)器確認(rèn)
第二次握手:服務(wù)端收到SYN 為 1 的客戶端連接請求報(bào)文后,需要對這個報(bào)文進(jìn)行確認(rèn),服務(wù)端將標(biāo)志位 SYN 與 ACK置為 1,設(shè)置 ack為 X+1, seq=Y(Y的值為 1-1234567 的隨機(jī)值),發(fā)回給客戶端,此時服務(wù)器進(jìn)入 SYN_RECV狀態(tài)
第三次握手:客戶端收到服務(wù)器的 ACK+SYN 報(bào)文,將ack設(shè)置為 Y+1,向服務(wù)器發(fā)送 ACK報(bào)文。這個報(bào)文發(fā)送完畢之后客戶端和服務(wù)器端都進(jìn)入了 ESTABLISHED 狀態(tài)
三次握手完成
備注:
ACK:此標(biāo)志表示應(yīng)答域有效,就是說前面所說的TCP應(yīng)答號將會包含在TCP數(shù)據(jù)包中;有兩個取值:0和1,為1的時候表示應(yīng)答域有效,反之為0。TCP協(xié)議規(guī)定,只有ACK=1時有效,也規(guī)定連接建立后所有發(fā)送的報(bào)文的ACK必須為1。?
?SYN(SYNchronization):在連接建立時用來同步序號。當(dāng)SYN=1而ACK=0時,表明這是一個連接請求報(bào)文。對方若同意建立連接,則應(yīng)在響應(yīng)報(bào)文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個連接請求或連接接受報(bào)文。?
?FIN(finis)即完,終結(jié)的意思, 用來釋放一個連接。當(dāng) FIN = 1 時,表明此報(bào)文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放連接。
補(bǔ)充:
路由尋址是什么?
客戶端封裝數(shù)據(jù)包,源地址為自己,目的地址為服務(wù)器 IP,通過 mac 地址表,走對應(yīng)交換機(jī)接口,傳輸?shù)铰酚善?,根?jù)路由器路由表找到每下一跳地址,進(jìn)行相應(yīng)數(shù)據(jù)轉(zhuǎn)發(fā),發(fā)送到服務(wù)器,服務(wù)器進(jìn)行數(shù)據(jù)解封裝處理。數(shù)據(jù)發(fā)回時同理為什么要三次握手?

"為了防止已失效的連接請求報(bào)文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯誤"
客戶端發(fā)送TCP連接請求報(bào)文,可是可能因?yàn)榫W(wǎng)絡(luò)問題,客戶端讓該鏈接超時失效。但服務(wù)器收到此失效報(bào)文后,誤認(rèn)為該客戶端請求連接,如果不采用三次握手,服務(wù)器發(fā)出確認(rèn),那么新的連接就建立了
客戶端收到服務(wù)器的確認(rèn)消息,并不會理睬也不會發(fā)送數(shù)據(jù)。
服務(wù)器以為連接已經(jīng)建立,一直等待,就造成資源浪費(fèi)
如果是三次握手,服務(wù)器收不到客戶端返回來的確認(rèn)報(bào)文,就知道客戶端并沒有要求建立連接
也避免了攻擊者持續(xù)發(fā)送TCP連接請求包,耗盡服務(wù)器資源
TCP連接建立后,瀏覽器就可以利用 HTTP協(xié)議向服務(wù)器發(fā)送請求了。
HTTP請求報(bào)文主要由請求行、請求頭、報(bào)文主體三部分組成

請求行:
由3部分組成,分別為:請求方法、URL(見備注1)以及協(xié)議版本,之間由空格分隔
請求方法包括GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE以及擴(kuò)展方法,當(dāng)然并不是所有的服務(wù)器都實(shí)現(xiàn)了所有的方法,部分方法即便支持,處于安全性的考慮也是不可用的
協(xié)議版本的格式為:HTTP/主版本號.次版本號,常用的有HTTP/1.0和HTTP/1.1

ps:
請求方法 GET 與 POST 之間有何區(qū)別?

"GET方法的數(shù)據(jù)參數(shù)是暴露在起始行的URL中的,而POST方法的數(shù)據(jù)參數(shù)是在報(bào)文主體中的。
GET方法相對來說沒有POST安全,因?yàn)樗臄?shù)據(jù)參數(shù)可以直接從URL中獲取,但是GET的效率更高。
GET方法的數(shù)據(jù)參數(shù)大小有一定的限制(1024)(原因也是因?yàn)樗臄?shù)據(jù)參數(shù)是放在URL中的),而POST對數(shù)據(jù)大小是沒有限制的。
其實(shí)他們的本質(zhì)區(qū)別是GET是從服務(wù)器上請求數(shù)據(jù),而POST是向服務(wù)器發(fā)送數(shù)據(jù)
請求頭:

Accept:告訴服務(wù)器當(dāng)前瀏覽器能接受和處理的介質(zhì)類型,*/*表示可接受所有類型。?
Accept-Encoding:告訴服務(wù)器當(dāng)前瀏覽器支持的內(nèi)容編碼。?
Accept-Language:告訴服務(wù)器當(dāng)前瀏覽器能接受和處理的語言。
Connection:keep-alive,告訴服務(wù)器在完成本次請求的響應(yīng)后,保持該TCP連接不釋放,等待本次連接的后續(xù)請求。這樣可以減少打開關(guān)閉TCP連接的次數(shù)提升處理性能。另外的可選項(xiàng)是Close,表明直接響應(yīng)接受完成后直接將其關(guān)閉。?
Host:接受請求的服務(wù)器地址,可以是IP:端口號,也可以是域名
User-Agent:發(fā)送請求的應(yīng)用程序名稱
Content-Length:用于描述HTTP消息實(shí)體的傳輸長度。
Content-Type:內(nèi)容類型,用于定義網(wǎng)絡(luò)文件的類型和網(wǎng)頁的編碼,決定瀏覽器將以什么形式、什么編碼讀取這個文件。
請求頭部最后有一個空行,表示請求頭部結(jié)束,后面就是請求正文了
請求正文:
可選,比如 GET 請求就沒有請求正文
HTTP 相應(yīng)報(bào)文主要由狀態(tài)行、響應(yīng)頭部、響應(yīng)正文三部分組成

狀態(tài)行:
由協(xié)議版本、狀態(tài)碼、狀態(tài)碼描述組成
狀態(tài)碼:
1XX:參考信息
2XX:狀態(tài)成功
3XX:用于重定向
4XX:客戶端錯誤
5XX:服務(wù)器端錯誤
列幾個常用的:

響應(yīng)頭:
與請求頭類似:
Server:服務(wù)器應(yīng)用程序軟件的名稱和版本
Content-Type:響應(yīng)正文的類型(是圖片還是二進(jìn)制字符串)
Content-Length:響應(yīng)正文長度
Content-Charset:響應(yīng)正文使用的編碼
Content-Encoding:響應(yīng)正文使用的數(shù)據(jù)壓縮格式
Content-Language:響應(yīng)正文使用的語言
瀏覽器拿到響應(yīng)文本后,解析HTML代碼,請求js,css等資源,最后進(jìn)行頁面渲染,呈現(xiàn)給用戶。頁面渲染一般分為以下幾個步驟:
(1)根據(jù)HTML文件解析出DOM Tree
(2)根據(jù)CSS解析出 CSSOM Tree(CSS規(guī)則樹)
(3)將 DOM Tree 和 CSSOM Tree合并,構(gòu)建Render tree(渲染樹)(4)reflow(重排):根據(jù)Render tree進(jìn)行節(jié)點(diǎn)信息計(jì)算(Layout)
(5)repaint(重繪):根據(jù)計(jì)算好的信息繪制整個頁面(Painting)
數(shù)據(jù)傳輸完畢,四次揮手,斷開連接

1、客戶端向服務(wù)端發(fā)送報(bào)文,F(xiàn)in、Ack、Seq,表示已經(jīng)沒有數(shù)據(jù)傳輸了。并進(jìn)入 FIN_WAIT_1 狀態(tài)。(由瀏覽器告訴服務(wù)器,我請求報(bào)文發(fā)送完了,你準(zhǔn)備關(guān)閉吧)
2、服務(wù)端向客戶端發(fā)送報(bào)文,Ack、Seq,表示同意關(guān)閉請求。此時主機(jī)發(fā)起方進(jìn)入 FIN_WAIT_2 狀態(tài)。(由服務(wù)器告訴瀏覽器,我請求報(bào)文接受完了,我準(zhǔn)備關(guān)閉了,你也準(zhǔn)備吧)
3、服務(wù)端向客戶端發(fā)送報(bào)文段,F(xiàn)in、Ack、Seq,請求關(guān)閉連接。并進(jìn)入 LAST_ACK 狀態(tài)。(由服務(wù)器告訴瀏覽器,我響應(yīng)報(bào)文發(fā)送完了,你準(zhǔn)備關(guān)閉吧)
4、客戶端向服務(wù)端發(fā)送報(bào)文段,Ack、Seq。然后進(jìn)入等待 TIME_WAIT 狀態(tài)。被動方收到發(fā)起方的報(bào)文段以后關(guān)閉連接。發(fā)起方等待一定時間未收到回復(fù),則正常關(guān)閉。(由瀏覽器告訴服務(wù)器,我響應(yīng)報(bào)文接受完了,我準(zhǔn)備關(guān)閉了,你也準(zhǔn)備吧)
還有什么問題,歡迎留言
以上~
END
