訪問Web通訊過程(http/tcp傳輸全過程,三次握手、請求、數據傳輸、四次揮手)

從輸入域名到最後呈現經歷的過程:

域名解析 --> 
發起TCP的3次握手 -->
創建TCP鏈接後發起http請求 -->
服務器響應http請求,瀏覽器獲得html代碼 -->
瀏覽器解析html代碼,並請求html代碼中的資源(如js、css、圖片等) -->
瀏覽器對頁面進行渲染呈現給用戶 -->
四次揮手結束

1.域名解析

首先瀏覽器會解析 www.zipackage.com 這個域名對應的IP地址。
① 瀏覽器 會首先搜索瀏覽器自身的DNS緩存(緩存時間比較短,大概只有1分鐘,且只能容納1000條緩存),
看自身的緩存中是否有www.zipackage.com 對應的條目,並且沒有過時,若是有且沒有過時則解析到此結束。
② 若是瀏覽器自身的緩存裏面沒有找到對應的條目,那麼瀏覽器會搜索操做系統自身的DNS緩存,若是找到且沒有過時則中止搜索解析到此結束.
③ 若是在Windows系統的DNS緩存也沒有找到,那麼嘗試讀取hosts文件(位於C:\Windows\System32\drivers\etc),
看看這裏面有沒有該域名對應的IP地址,若是有則解析成功。
④ 若是在hosts文件中也沒有找到對應的條目,瀏覽器就會發起一個DNS的系統調用,
就會向本地配置的首選DNS服務器(通常是電信運營商提供的)發起域名解析請求(經過的是UDP協議向DNS的53端口發起請求,
這個請求是遞歸的請求,也就是運營商的DNS服務器必須得提供給咱們該域名的IP地址),運營商的DNS服務器首先查找自身的緩存,
找到對應的條目,且沒有過時,則解析成功。
若是沒有找到對應的條目,則有運營商的DNS代咱們的瀏覽器發起迭代DNS解析請求,
它首先是會找根域的DNS的IP地址(這個DNS服務器都內置13臺根域的DNS的IP地址),找到根域的DNS地址,就會向其發起請求

(請問www.zipackage.com這個域名的IP地址是多少啊?)
根域發現這是一個頂級域com域的一個域名,
因而就告訴運營商的DNS我不知道這個域名的IP地址,可是我知道com域的IP地址,你去找它去,
因而運營商的DNS就獲得了com域的IP地址,又向com域的IP地址發起了請求

(請問www.zipackage.com這個域名的IP地址是多少
?),
com域這臺服務器告訴運營商的DNS我不知道www.zipackage.com這個域名的IP地址,可是我知道zipackage.com這個域的DNS地址,你去找它去,
因而運營商的DNS又向zipackage.com這個域名的DNS地址(這個通常就是由域名註冊商提供的,像萬網,新網等)發起請求

(請問www.zipackage.com這個域名的IP地址是多少?)
這個時候zipackage.com域的DNS服務器一查,
誒,果然在我這裏,因而就把找到的結果發送給運營商的DNS服務器,
這個時候運營商的DNS服務器就拿到了www.zipackage.com這個域名對應的IP地址,
並返回給Windows系統內核,內核又把結果返回給瀏覽器,
終於瀏覽器拿到了www.zipackage.com 對應的IP地址,該進行一步的動做了。

2.發起TCP的3次握手

拿到域名對應的IP地址以後,User-Agent(通常是指瀏覽器)
會以一個隨機端口(1024 < 端口 < 65535)向服務器的WEB程序(經常使用的有httpd,nginx等)80端口發起TCP的鏈接請求。
這個鏈接請求(原始的http請求通過TCP/IP4層模型的層層封包)到達服務器端後(這中間經過各類路由設備,局域網內除外),進入到網卡,
而後是進入到內核的TCP/IP協議棧(用於識別該鏈接請求,解封包,一層一層的剝開),
還有可能要通過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序。
1) Client首先發送一個鏈接試探,ACK=0 表示確認號無效,SYN = 1 表示這是一個鏈接請求或鏈接接受報文,
同時表示這個數據報不能攜帶數據,seq = x 表示Client本身的初始序號(seq = 0 就表明這是第0號幀),
這時候Client進入syn_sent狀態,表示客戶端等待服務器的回覆
2) Server監聽到鏈接請求報文後,如贊成創建鏈接,則向Client發送確認。
TCP報文首部中的SYN 和 ACK都置1 ,ack = x + 1表示指望收到對方下一個報文段的第一個數據字節序號是x+1
同時代表x爲止的全部數據都已正確收到(ack=1實際上是ack=0+1,也就是指望客戶端的第1個幀),
seq = y 表示Server 本身的初始序號(seq=0就表明這是服務器這邊發出的第0號幀)。
這時服務器進入syn_rcvd,表示服務器已經收到Client的鏈接請求,等待client的確認。
3) Client收到確認後還需再次發送確認,同時攜帶要發送給Server的數據。ACK 置1 表示確認號ack= y + 1 有效(表明指望收到服務器的第1個幀),
Client本身的序號seq= x + 1(表示這就是個人第1個幀,相對於第0個幀來講的),一旦收到Client的確認以後,
這個TCP鏈接就進入Established狀態,就能夠發起http請求了。

3.創建TCP鏈接後發起http請求

進過TCP3次握手以後,瀏覽器發起了http的請求(第4幀),使用的http的方法 GET 方法,協議是HTTP/1.1

4.服務器端響應http請求,瀏覽器獲得html代碼

服務器端WEB程序接收到http請求之後,就開始處理該請求,處理以後就返回給瀏覽器html文件。

 

前面3個tcp包爲3次握手的過程,主機向服務器發送一個http應用請求,服務器收到請求後,返回一個tcp確認幀(第5幀),
接着發送一個http應答給主機(載有實際數據,第6,7幀,因爲數據較大,分紅多個包傳輸),
主機收到服務器的http應答數據後,又發送一個tcp確認幀(第8幀),確認收到了數據,反覆進行傳輸,應答,直到全部數據傳輸完成(6到18幀)。 第4號包是http請求包,第19號包是http響應包

如下是數據傳輸包含的內容:

5. 瀏覽器解析html代碼,並請求html代碼中的資源

瀏覽器拿到index.html文件後,就開始解析其中的html代碼,遇到js/css/image等靜態資源時,就向服務器端去請求下載(會使用多線程下載,
每一個瀏覽器的線程數不同),這個時候就用上keep-alive特性了,創建一次HTTP鏈接,能夠請求多個資源,下載資源的順序就是按照代碼裏的順序。 瀏覽器在請求靜態資源時(在未過時的狀況下),向服務器端發起一個http請求(詢問自從上一次修改時間到如今有沒有對資源進行修改),
若是服務器端返回304狀態碼(告訴瀏覽器服務器端沒有修改),那麼瀏覽器會直接讀取本地的該資源的緩存文件。
HTTP1.0和HTTP1.1的區別
在HTTP1.0協議中,客戶端與web服務器創建鏈接後,只能得到一個web資源。
HTTP1.1協議,容許客戶端與web服務器創建鏈接後,在一個鏈接上獲取多個web資源。

6.瀏覽器對頁面進行渲染呈現給用戶

瀏覽器利用本身內部的工做機制,把請求到的靜態資源和html代碼進行渲染,渲染以後呈現給用戶。

7.傳輸完成,斷開四次揮手

斷開鏈接端能夠是Client端,也能夠是Server端。假設Client端發起中斷鏈接請求:
第一次揮手:客戶端先發送FIN報文(第24幀),用來關閉主動方到被動關閉方的數據傳送,也就是客戶端告訴服務器:
我已經不會再給你發數據了(固然,在fin包以前發送出去的數據,
若是沒有收到對應的ack確認報文,客戶端依然會重發這些數據),但此時客戶端還能夠接受數據。
第二次揮手:Server端接到FIN報文後,可是若是還有數據沒有發送完成,則沒必要急着關閉Socket,能夠繼續發送數據。
因此服務器端先發送ACK(第25幀),告訴Client端:請求已經收到了,可是我還沒準備好,請繼續等待中止的消息。
這個時候Client端就進入FIN_WAIT狀態,繼續等待Server端的FIN報文。
第三次揮手:當Server端肯定數據已發送完成,則向Client端發送FIN報文(第26幀),告訴Client端:服務器這邊數據發完了,準備好關閉鏈接了。
第四次揮手:Client端收到FIN報文後,就知道能夠關閉鏈接了,可是他仍是不相信網絡,因此發送ACK後進入TIME_WAIT狀態(第27幀), Server端收到ACK後,就知道能夠斷開鏈接了。Client端等待了2MSL後依然沒有收到回覆,則證實Server端已正常關閉,最後,Client端也能夠關閉鏈接了至此,TCP鏈接就已經徹底關閉了!
相關文章
相關標籤/搜索