最近工做之餘一直在溫故js系列,想知新,想提高,以小技術點爲節奏去回顧。今天忽然想到回顧一下這個http知識,http知識有太多深層次須要學習,今天簡要回顧,淺析下這個技術點。
主要經過五個步驟淺析這個過程,有錯誤的地方,煩請斧正,互相學習。javascript
當發送一個URL請求時,無論這個URL是Web頁面的URL仍是Web頁面上每一個資源的URL,瀏覽器都會開啓一個線程來處理這個請求,同時在遠程DNS服務器上啓動一個DNS查詢,讓瀏覽器得到請求對應的IP地址。
(這兒涉及的「DNS 查詢和經過 Socket 發送數據」知識點見連接文章)前端
瀏覽器與遠程 Web 服務器經過 TCP 三次握手協商來創建一個 TCP/IP 鏈接。該握手包括一個同步報文,一個同步-應答報文和一個應答報文,這三個報文在 瀏覽器和服務器之間傳遞。該握手首先由客戶端嘗試創建起通訊,然後服務器應答並接受客戶端的請求,最後由客戶端發出該請求已經被接受的報文。
java
ACK: ACK=1表示該報文段中有確認號須要處理。 SYN: SYN=1 ACK=0代表是創建鏈接請求報文段,SYN=1 ACK=1代表贊成創建鏈接報文。 FIN: FIN=1表示對端的數據已經發送完畢,要求釋放鏈接。
客戶端發送鏈接請求報文段,將SYN值設爲1,Sequence Number
爲x。客戶端進入SYN_SEND
狀態,等待服務器的確認。node
服務器收到客戶端SYN報文段,須要對這個SYN報文段進行確認,設置Acknowledgment Number
爲x+1(Sequence Number+1
)。同時,本身本身還要發送SYN請求信息,將SYN值設爲1,Sequence Number
設爲y。服務器端將上述全部信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,服務器進入SYN_RECV
狀態。git
客戶端收到服務器的SYN+ACK報文段後將Acknowledgment Number
設置爲y+1,向服務器發送ACK報文段,這個報文段發送完畢之後,客戶端和服務器端都進入ESTABLISHED
狀態,完成TCP三次握手。github
完成三次握手,客戶端與服務器開始傳送數據,在上述過程當中,還有一些重要的概念: 面試
未鏈接隊列:在三次握手協議中,服務器維護一個未鏈接隊列,該隊列爲每一個客戶端的SYN包(syn=j
)開設一個條目,該條目代表服務器已收到SYN包,並向客戶發出確認,正在等待客戶的確認包。這些條目所標識的鏈接在服務器處於Syn_RECV
狀態,當服務器收到客戶的確認包時,刪除該條目,服務器進入ESTABLISHED
狀態。 Backlog參數
:表示未鏈接隊列的最大容納數目。 segmentfault
SYN-ACK 重傳次數:服務器發送完SYN-ACK
包,若是未收到客戶確認包,服務器進行首次重傳,等待一段時間仍未收到客戶確認包,進行第二次重傳,若是重傳次數超過系統規定的最大重傳次數,系統將該鏈接信息從未鏈接隊列中刪除。注意,每次重傳等待的時間不必定相同。 瀏覽器
未鏈接存活時間:是指未鏈接隊列的條目存活的最長時間,也即服務從收到SYN包到確認這個報文無效的最長時間,該時間值是全部重傳請求包的最長等待時間總和。有時咱們也稱未鏈接存活時間爲Timeout時間、SYN_RECV
存活時間。服務器
圖片及問題轉自jimmy_thr的https://segmentfault.com/a/11...
很簡單呀,由於3次就夠了,幹嗎用4次。23333. 舉個例子吧,假如是2次的話, 可能會出現這樣一個狀況。
當客戶端發送一次請求A後,可是A在網絡延遲了好久, 接着客戶端又發送了一次B,可是此時A已經無效了。 接着服務器相應了B,並返回TCP鏈接頭,創建鏈接(這裏就2次哈)。 而後,A 歷經千山萬水終於到服務器了, 服務器一看有請求來了,則接受,因爲一開始A帶着的TCP格式都是正確的,那麼服務器,理所應當的也返回成功鏈接的flag,可是,此時客戶端已經判斷該次請求無效,廢棄了。 而後服務器,就這麼一直掛着(浪費資源),形成的一個問題是,md, 這個鍋是誰的? 因此,爲了保險起見,再補充一次鏈接就能夠了。因此3次是最合適的。在Chinese中,以3爲起稱爲多,若是你用4,5,6,7,8...次的話,這不更浪費嗎?
TCP/IP 鏈接創建後,瀏覽器會經過該鏈接向遠程服務器發送 HTTP 的 GET 請求。遠程服務器找到資源並使用 HTTP 響應返回該資源,值爲200的 HTTP 響應狀態表示一個正確的響應。
客戶端開始下載資源。請求返回後,便進入了咱們關注的前端模塊。瀏覽器會解析 HTML 成樹形的數據結構DOM,生成 DOM Tree
,瀏覽器將CSS代碼解析成樹形的數據結構CSSOM,生成 CSS Rule Tree
。
DOM 和 CSSOM 都是以 Bytes → characters → tokens → nodes → object model
這樣的方式生成最終的數據。DOM樹的構建過程是一個深度遍歷過程:當前節點的全部子節點都構建好後纔會去構建當前節點的下一個兄弟節點。
DOM Tree
和CSS Rule Tree
結合生成Render Tree
。
display:none 的節點不會被加入Render Tree,而visibility: hidden 則會。
• display : 隱藏對應的元素但不擠佔該元素原來的空間。
• visibility: 隱藏對應的元素而且擠佔該元素原來的空間
因此,若是某個節點最開始是不顯示的,設爲display:none是更優的。
有了Render Tree,瀏覽器知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係。接着就開始佈局,計算出每一個節點在屏幕中的位置。
瀏覽器已經知道了哪些節點要顯示、每一個節點的CSS屬性是什麼、每一個節點在屏幕中的位置是哪裏。就進入了最後一步,按照算出來的規則,經過顯卡,把內容畫到屏幕上。
而 javascript 又能夠根據 DOM API 操做DOM。好比JS修改了DOM或者CSS屬性,也會從新觸發佈局和渲染的執行過程。
關於這個問題到這兒就能夠結束了......圖已放,情未了,那順便把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.