天天看點

TCP三向交握&Render Tree頁面渲染=>從輸入URL到頁面顯示的過程?

最近工作之餘一直在溫故js系列,想知新,想提升,以小技術點為節奏去回顧。今天突然想到回顧一下這個http知識,http知識有太多深層次需要學習,今天簡要回顧,淺析下這個技術點。

主要通過五個步驟淺析這個過程,有錯誤的地方,煩請斧正,互相學習。

這個知識太複雜了,以前看的時候頭暈o(∩_∩)o~

1、發送url,請求ip位址

當發送一個url請求時,不管這個url是web頁面的url還是web頁面上每個資源的url,浏覽器都會開啟一個線程來處理這個請求,同時在遠端dns伺服器上啟動一個dns查詢,讓浏覽器獲得請求對應的ip位址。(這兒涉及的“dns

查詢和通過 socket 發送資料”知識點見連結文章)

2、tcp三次握手

浏覽器與遠端 web 伺服器通過 tcp 三次握手協商來建立一個 tcp/ip

連接配接。該握手包括一個同步封包,一個同步-應答封包和一個應答封包,這三個封包在

浏覽器和伺服器之間傳遞。該握手首先由用戶端嘗試建立起通信,而後伺服器應答并接受用戶端的請求,最後由用戶端發出該請求已經被接受的封包。

TCP三向交握&Render Tree頁面渲染=>從輸入URL到頁面顯示的過程?

ack: ack=1表示該封包段中有确認号需要處理。

syn: syn=1 ack=0表明是建立連接配接請求封包段,syn=1 ack=1表明同意建立連接配接封包。

fin: fin=1表示對端的資料已經發送完畢,要求釋放連接配接。

第一次握手:建立連接配接

用戶端發送連接配接請求封包段,将syn值設為1,sequence number為x。用戶端進入syn_send狀态,等待伺服器的确認。

第二次握手:伺服器收到syn封包段

伺服器收到用戶端syn封包段,需要對這個syn封包段進行确認,設定acknowledgment number為x+1(sequence

number+1)。同時,自己自己還要發送syn請求資訊,将syn值設為1,sequence

number設為y。伺服器端将上述所有資訊放到一個封包段(即syn+ack封包段)中,一并發送給用戶端,伺服器進入syn_recv狀态。

第三次握手:用戶端收到syn+ack封包段

用戶端收到伺服器的syn+ack封包段後将acknowledgment number設定為y+1,向伺服器發送ack封包段,這個封包段發送完畢以後,用戶端和伺服器端都進入established狀态,完成tcp三次握手。

完成三次握手,用戶端與伺服器開始傳送資料,在上述過程中,還有一些重要的概念:

未連接配接隊列:在三次握手協定中,伺服器維護一個未連接配接隊列,該隊列為每個用戶端的syn包(syn=j)開設一個條目,該條目表明伺服器已收到syn包,并向客戶發出确認,正在等待客戶的确認包。這些條目所辨別的連接配接在伺服器處于syn_recv狀态,當伺服器收到客戶的确認包時,删除該條目,伺服器進入established狀态。

backlog參數:表示未連接配接隊列的最大容納數目。

syn-ack

重傳次數:伺服器發送完syn-ack包,如果未收到客戶确認包,伺服器進行首次重傳,等待一段時間仍未收到客戶确認包,進行第二次重傳,如果重傳次數超過系統規定的最大重傳次數,系統将該連接配接資訊從半連接配接隊列中删除。注意,每次重傳等待的時間不一定相同。

半連接配接存活時間:是指半連接配接隊列的條目存活的最長時間,也即服務從收到syn包到确認這個封包無效的最長時間,該時間值是所有重傳請求包的最長等待時間總和。有時我們也稱半連接配接存活時間為timeout時間、syn_recv存活時間。

為什麼是3次握手?

很簡單呀,因為3次就夠了,幹嘛用4次。23333. 舉個例子吧,假如是2次的話, 可能會出現這樣一個情況。

當用戶端發送一次請求a後,但是a在網絡延遲了很久, 接着用戶端又發送了一次b,但是此時a已經無效了。

接着伺服器相應了b,并傳回tcp連接配接頭,建立連接配接(這裡就2次哈)。 然後,a 曆經千山萬水終于到伺服器了,

伺服器一看有請求來了,則接受,由于一開始a帶着的tcp格式都是正确的,那麼伺服器,理所應當的也傳回成功連接配接的flag,但是,此時用戶端已經判斷該次請求無效,廢棄了。

然後伺服器,就這麼一直挂着(浪費資源),造成的一個問題是,md, 這個鍋是誰的?

是以,為了保險起見,再補充一次連接配接就可以了。是以3次是最合适的。在chinese中,以3為起稱為多,如果你用4,5,6,7,8...次的話,這不更浪費嗎?

3、伺服器響應200

tcp/ip 連接配接建立後,浏覽器會通過該連接配接向遠端伺服器發送 http 的 get 請求。遠端伺服器找到資源并使用 http 響應傳回該資源,值為200的 http 響應狀态表示一個正确的響應。

4、生成render tree

用戶端開始下載下傳資源。請求傳回後,便進入了我們關注的前端子產品。浏覽器會解析 html 成樹形的資料結構dom,生成 dom tree,浏覽器将css代碼解析成樹形的資料結構cssom,生成 css rule tree。

dom 和 cssom 都是以 bytes → characters → tokens → nodes → object model

這樣的方式生成最終的資料。dom樹的建構過程是一個深度周遊過程:目前節點的所有子節點都建構好後才會去建構目前節點的下一個兄弟節點。

TCP三向交握&Render Tree頁面渲染=>從輸入URL到頁面顯示的過程?

dom tree和css rule tree結合生成render tree。

TCP三向交握&Render Tree頁面渲染=>從輸入URL到頁面顯示的過程?

display:none 的節點不會被加入render tree,而visibility: hidden 則會。

• display : 隐藏對應的元素但不擠占該元素原來的空間。

• visibility: 隐藏對應的元素并且擠占該元素原來的空間

是以,如果某個節點最開始是不顯示的,設為display:none是更優的。

5、渲染頁面

布局

有了render tree,浏覽器知道網頁中有哪些節點、各個節點的css定義以及他們的從屬關系。接着就開始布局,計算出每個節點在螢幕中的位置。

渲染

浏覽器已經知道了哪些節點要顯示、每個節點的css屬性是什麼、每個節點在螢幕中的位置是哪裡。就進入了最後一步,按照算出來的規則,通過顯示卡,把内容畫到螢幕上。

而 javascript 又可以根據 dom api 操作dom。比如js修改了dom或者css屬性,也會重新觸釋出局和渲染的執行過程。

關于這個問題到這兒就可以結束了......圖已放,情未了,那順便把tcp四次揮手也寫這,結合圖去分析。

遺留:tcp四次揮手

第一次揮手:用戶端想分手

假設用戶端想要關閉連接配接,用戶端發送一個 fin 标志位置為1的包(fin=1,seq=x),表示自己已經沒有資料可以發送了,但是仍然可以接受資料。

發送完畢後,用戶端進入 fin_wait_1 狀态。

第二次揮手:服務端也想分手

伺服器端确認用戶端的 fin包,發送一個确認包(ack=1,acknum=x+1),表明自己接受到了用戶端關閉連接配接的請求,但還沒有準備好關閉連接配接。

發送完畢後,伺服器端進入 close_wait 狀态,用戶端接收到這個确認包之後,進入fin_wait_2 狀态,等待伺服器端關閉連接配接。

第三次揮手:服務端準備好分手

伺服器端準備好關閉連接配接時,向用戶端發送結束連接配接請求,fin置為1(fin=1,seq=y)。

發送完畢後,伺服器端進入 last_ack 狀态,等待來自用戶端的最後一個ack。

第四次揮手:分手

用戶端接收到來自伺服器端的關閉請求,發送一個确認包(ack=1,acknum=y+1),并進入 time_wait狀态,等待可能出現的要求重傳的 ack包。

伺服器端接收到這個确認包之後,關閉連接配接,進入 closed 狀态。

用戶端等待2msl(2msl,2 maximum segment lifetime)之後,沒有收到回複,確定伺服器端确實是關閉了,用戶端也關閉連接配接,進入 closed狀态。

學知識不會是為了面試,因為面試會一層層的深入,不知道的就是不知道,不能逞強,最後坑了自己。多研究研究,才是真理。come on , basketball.

作者:xzavier

來源:51cto

繼續閱讀