文章目錄
- 訪問一個網頁的全過程
- 應用層
- 在瀏覽器輸入URL網址http://www.aspxfans.com:8080/news/index.aspboardID=5&ID=24618&page=1#r_70732423
- 通過DNS獲取IP地址
- 生成HTTP請求報文
- 應用層最后
- 傳輸層
- 傳輸層處理應用層報文
- 建立TCP連接
- 傳輸層最后
- 網絡層
- 網絡層對TCP報文進行處理
- 網絡層的轉發
- 網絡層的最后
- 數據鏈路層
- 對IP數據報的處理
- 數據鏈路層的MAC尋址
- 數據鏈路層的最后
- 物理層
- 對MAC幀的處理
- 服務器響應
- 服務端將數據包通過數據鏈路層->網絡層->傳輸層一層層的解封,最后處理HTTP中的請求
- 發出HTTP響應報文
- cookie
- 瀏覽器解析響應報文
- 瀏覽器解析html代碼,并請求html代碼中的資源
- 瀏覽器渲染
- TCP連接斷開
- 四次揮手結束TCP傳輸
訪問一個網頁的全過程
應用層
在瀏覽器輸入URL網址http://www.aspxfans.com:8080/news/index.aspboardID=5&ID=24618&page=1#r_70732423
URL格式示例
一個完整的URL包括:協議部分、域名部分、端口部分、虛擬目錄部分、文件名部分、參數部分、錨部分
1.協議部分:該URL的協議部分為“http:”,這代表網頁使用的是HTTP協議。在Internet中可以使用多種協議,如HTTP,FTP等等本例中使用的是HTTP協議。在”HTTP”后面的“//”為分隔符
2.域名部分:該URL的域名部分為“www.aspxfans.com”。
3.端口部分:跟在域名后面的是端口,域名和端口之間使用“:”作為分隔符。端口不是一個URL必須的部分,如果省略端口部分,將采用默認端口
4.虛擬目錄部分:從域名后的第一個“/”開始到最后一個“/”為止,是虛擬目錄部分。虛擬目錄也不是一個URL必須的部分。本例中的虛擬目錄是“/news/”
5.文件名部分:從域名后的最后一個“/”開始到“?”為止,是文件名部分,如果沒有“?”,則是從域名后的最后一個“/”開始到“#”為止,是文件部分,如果沒有“?”和“#”,那么從域名后的最后一個“/”開始到結束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一個URL必須的部分,如果省略該部分,則使用默認的文件名
7.參數部分:從“?”開始到“#”為止之間的部分為參數部分,又稱搜索部分、查詢部分。本例中的參數部分為“boardID=5&ID=24618&page=1”。參數可以允許有多個參數,參數與參數之間用“&”作為分隔符。
8.錨部分:HTTP請求不包括錨部分,從“#”開始到最后,都是錨部分。本例中的錨部分是“r_70732423“。錨部分也不是一個URL必須的部分。
錨點作用:打開用戶頁面時滾動到該錨點位置。如:一個html頁面中有一段代碼,該url的hash為r_70732423, 打開上面的URL, 用戶頁面會滾動到name='r_70732423’的代碼塊.
通過DNS獲取IP地址
-
如果平臺配備了負載均衡的話,前一步DNS解析獲得的IP地址應該是Nginx負載均衡服務器的IP地址。所以,之后會將我們的網頁請求發送到了Nginx負載均衡服務器上。
Nginx根據我們設定的分配算法和規則,選擇一臺后端的真實Web服務器,與之建立TCP連接、并轉發我們瀏覽器發出去的網頁請求。 -
DNS詳細步驟(以迭代查詢為例)
- 檢查瀏覽器緩存.
本地電腦會檢查瀏覽器緩存中有沒有這個域名對應的解析過的IP地址,如果緩存中有,這個解析過程就結束。瀏覽器緩存域名也是有限制的,不僅瀏覽器緩存大小有限制,而且緩存的時間也有限制,通常情況下為幾分鐘到幾小時不等,域名被緩存的時間限制可以通過TTL屬性來設置。這個緩存時間太長和太短都不太好,如果時間太長,一旦域名被解析到的IP有變化,會導致被客戶端緩存的域名無法解析到變化后的IP地址,以致該域名不能正常解析,這段時間內有一部分用戶無法訪問網站。如果設置時間太短,會導致用戶每次訪問網站都要重新解析一次域名。
- 檢查操作系統緩存
如果瀏覽器緩存中沒有數據,瀏覽器會查找操作系統緩存中是否有這個域名對應的DNS解析結果。其實操作系統也有一個域名解析的過程,在Linux中可以通過/etc/hosts文件來設置,而在windows中可以通過配置C:\Windows\System32\drivers\etc\hosts文件來設置,用戶可以將任何域名解析到任何能夠訪問的IP地址。例如,我們在測試時可以將一個域名解析到一臺測試服務器上,這樣不用修改任何代碼就能測試到單獨服務器上的代碼的業務邏輯是否正確。正是因為有這種本地DNS解析的規程,所以有黑客就可能通過修改用戶的域名來把特定的域名解析到他指定的IP地址上,導致這些域名被劫持。
- 以UDP方式發出由本地DNS客戶端構造的DNS請求報文給本地域名服務器,本地域名服務器查看緩存的解析結果。
前兩個過程無法解析時,就要用到我們網絡配置中的"DNS服務器地址"了。操作系統會把這個域名發送給這個本地DNS服務器。每個完整的內網通常都會配置本地DNS服務器,例如用戶是在學校或工作單位接入互聯網,那么用戶的本地DNS服務器肯定在學校或工作單位里面。它們一般都會緩存域名解析結果,當然緩存時間是受到域名的失效時間控制的。大約80%的域名解析到這里就結束了,后續的DNS迭代和遞歸也是由本地DNS服務器負責。
- 本地域名服務器未命中,發送解析請求報文給根DNS服務器。(本地DNS第一次)
如果本地DNS服務器仍然沒有命中,就直接到根DNS服務器請求解析。
- 根域名服務器返回com.域的頂級域名服務器GTLS-DNS
根DNS服務器返回給本地DNS域名服務器一個頂級DNS(按例子中為com.域服務器)服務器地址,它是國際頂級域名服務器,如.com、.cn、.org等,全球只有13臺左右。
- 本地服務器繼續發送解析請求報文給頂級DNS服務器。(本地DNS第二次)
本地DNS服務器再向上一步獲得的頂級DNS服務器發送解析請求。
- 頂級DNS服務器返回權威服務器的IP地址。
接受請求的頂級DNS服務器查找并返回此域名對應的Name Server域名服務器的地址,這個Name Server服務器就是我要訪問的網站域名提供商的服務器,其實該域名的解析任務就是由域名提供商的服務器來完成。比如我要訪問www.baidu.com,而這個域名是從A公司注冊獲得的,那么A公司上的服務器就會有www.baidu.com的相關信息。
- 本地DNS繼續向權威域名服務器發送解析請求(本地DNS第三次,注意這里大部分情況是3次,但遇到域名很長的name server服務器可能會有多級)
Name Server服務器會查詢存儲的域名和IP的映射關系表,再把查詢出來的域名和IP地址等等信息,連同一個TTL值返回給本地DNS服務器。
- 本地DNS接收到之后緩存對應域名和IP的對應關系,并返回給主機
返回該域名對應的IP和TTL值,本地DNS服務器會緩存這個域名和IP的對應關系,緩存時間由TTL值控制。
- 主機收到結果緩存到本地緩存
把解析的結果返回給本地電腦,本地電腦根據TTL值緩存在本地系統緩存中,域名解析過程結束在實際的DNS解析過程中,可能還不止這10步,如Name Server可能有很多級,或者有一個GTM來負載均衡控制,這都有可能會影響域名解析過程。
生成HTTP請求報文
使用HTTP協議生成HTTP請求報文
應用層最后
將所產生的數據報文傳送到傳輸層
傳輸層
傳輸層處理應用層報文
- 將HTTP請求報文按序號分為多個報文段(segment),并對每個報文段進行封裝(加入TCP首部)。
- TCP視應用層下發的http請求報文為字節流,TCP協議會根據規定的**MSS(最大報文長度:規定了TCP報文所能攜帶的數據載荷的大小)**判斷是否進行拆分
- 如果字節流長度大于MSS,則需要進行拆分,拆分成合理的幾塊,然后為每一塊添加上合適的TCP頭部
- TCP頭部中的序號字段就是為此服務的,最終形成一個個TCP報文段,接收方對應的運輸層收到這些TCP報文段后可以根據TCP頭部信息進行組裝還原原來的http請求報文
建立TCP連接
- 建立TCP連接
通過三次握手建立連接
傳輸層最后
- 將封裝好的TCP報文傳送到網絡層
網絡層
網絡層對TCP報文進行處理
- 對TCP報文進行封裝以及分片
- 根據TCP報文端的類型選擇不同的協議。協議字段值為6表示TCP,17表示UDP
- IP協議會根據輸出端口(其實也就是被鏈路層的各種協議類型所規定)的**MTU(最大傳輸單元:它規定了IP網絡包的最大長度包括首部和數據載荷)**進行判斷是否進行分片;
- 分片是IP對整個TCP報文段一視同仁,也就是不會區分是TCP頭部還是數據載荷
- 這里會加入源IP地址和目的IP地址,一般情況下不會改變(NAT路由器會將其改變,會更改其端口號和源地址[即為NAT路由器的外網IP地址],服務器響應的目的地址也為NAT的IP地址)
網絡層的轉發
主機將其封裝好后會發往與其直接相連的交換結點。(路由器只使用協議棧的下三層)
路由器在將主機發送的MAC幀拆封,在收到IP分組之后,路由器會查找路由表得到下一跳的IP地址,首先將IP報文中的目的地址和路由表項中的子網掩碼進行"邏輯與"操作,得到一個網絡地址,然后拿此網絡地址與路由項中的網絡地址做比較,如果一致就認為匹配,否則認為不匹配。
如果沒有路由項能夠匹配,則丟棄該IP報文并發送ICMP報文。
網絡層的最后
在得到下一跳的IP地址后,利用ARP協議轉換為MAC地址后,需要將其連同IP數據報交付給數據鏈路層。
- 根據ARP協議將下一跳的IP地址轉換為MAC地址
- 主機A首先查看自己的ARP表,確定其中是否包含有主機B對應的ARP表項。如果找到了對應的MAC地址,則主機A直接利用ARP表中的MAC地址,對IP數據包進行幀封裝,并將數據包發送給主機B。
- 如果主機A在ARP表中找不到對應的MAC地址,則將緩存該數據報文,然后以廣播方式發送一個ARP請求報文。(詳情可以看4.2IPV4)
ARP請求報文中的發送端IP地址和發送端MAC地址為主機A的IP地址和MAC地址,目標IP地址和目標MAC地址為主機B的IP地址和全0的MAC地址。由于ARP請求報文以廣播方式發送,該網段上的所有主機都可以接收到該請求,但只有被請求的主機(即主機B)會對該請求進行處理。
如果是向另一網絡上的主機進行發送和,則路由器會響應給其對應的硬件地址
- 主機B比較自己IP地址和ARP請求報文中的目標IP地址,當兩者相同時進行如下處理:將ARP請求報文中的發送端(即主機A)的IP地址和MAC地址存入自己的ARP表中。
之后以單播方式發送ARP響應報文給主機A,其中包含了自己的MAC地址。- 主機A收到ARP響應報文后,將主機B的MAC地址加入到自己的ARP表中以用于后續報文的轉發,同時將IP數據包進行封裝后發送出去。
ARP協議在OSI參考模型中屬于數據鏈路層,而在TCP/IP模型中屬于網絡層**。
ARP(地址解析協議)是一個用于將網絡層的IP地址轉換為數據鏈路層的物理地址(如以太網MAC地址)的協議。在兩個不同的網絡模型中,ARP的位置有所不同:
- 在OSI模型中:ARP工作在數據鏈路層。這是因為ARP的主要功能是在同一局域網內解析出設備的物理地址,這個過程涉及到數據鏈路層的幀和物理層的硬件地址。
- 在TCP/IP模型中:ARP被視為網絡層的一部分。這是因為ARP為IP地址到物理地址的映射提供服務,而IP地址是網絡層的概念。在TCP/IP模型中,ARP直接生成自己的報文,不需要經過IP協議的封裝,然后這些報文會被數據鏈路層協議(如以太網)進一步封裝。
基于功能來考慮,ARP是鏈路層協議;基于分層/包封裝來考慮,ARP是網絡層協議。
數據鏈路層
對IP數據報的處理
在得到對應的MAC地址和IP數據報后可以將其封裝成MAC幀
- 將IP數據報進行封裝成幀
封裝成幀是指數據鏈路層給上層交付的協議數據單元添加幀頭和幀尾使之成為幀。
幀頭和幀尾中包含有重要的控制信息。(源地址為本機MAC地址,目的地址為上層交付到的MAC地址,這里MAC地址可以說是適配器的MAC地址(網卡))
幀頭和幀尾的作用之一就是幀定界
數據鏈路層的MAC尋址
- 交換機:
工作在數據鏈路層,是基于MAC地址識別,能夠完成數據包封裝轉發的網絡設備;主要用于構建局域網;具有流量控制能力;交換機有自學習功能,并且學習過的內容不是一直保存的,在經過一定時間就會刪除。所以交換表有三列:MAC地址 端口 寫入時間 - 交換機在使用直通交換時,轉發MAC幀只檢查幀的目的MAC地址(6B)以此決定轉發端口。缺點是不檢查差錯,可能將無效幀給轉發給其他的站。
- 兜圈子:從所有端口轉發很可能就不斷的進行循環,造成資源浪費:采用生成樹協議去邏輯上切斷某些鏈路,使得一臺主機到所有其他主機的路徑是無環路的樹狀結構。
MAC地址尋址是,首先通過廣播包獲取足夠的MAC地址表,然后維護這個MAC地址表(反映各端口與MAC地址之間的關系,便于后面的數據轉發)
數據鏈路層的最后
將MAC幀交付給物理層
物理層
對MAC幀的處理
- 插入8B的前導碼,通過物理層將構成幀的各比特,轉換成電信號發送到傳輸媒體
- 前導碼中的前7個字節為前同步碼,作用是便接收萬的時鐘同步。
- 之后的1字節為幀開始定界符,表明其后面是跟著的就是MAC幀。
- 另外,以太網還規定了幀間可隔時間為96比特的發送時間。
- 因此,MAC幀并不需要幀結束定界符。
服務器響應
服務端將數據包通過數據鏈路層->網絡層->傳輸層一層層的解封,最后處理HTTP中的請求
發出HTTP響應報文
- HTTP響應包含以下內容:
狀態行:包括HTTP版本、響應狀態碼和對應的狀態消息;
響應頭部:包括一系列關于響應的元數據,如Content-Type、Content-Length、Server等;
空行:響應頭部和響應正文之間需要空一行;
響應正文:包含響應的數據,如HTML、XML、JSON等文檔格式、圖片、音頻、視頻等二進制數據等等。
- HTTP響應報文狀態碼
狀態碼(status code)是在HTTP協議中用于表示服務器對客戶端請求的處理結果的數字代碼。通過狀態碼,客戶端可以了解到請求的處理結果,如訪問是否成功、是否需要重定向、是否存在錯誤等。
1xx:信息性響應
100:繼續(Continue)- 表示服務器接收到請求,客戶端可以繼續發送請求的剩余部分。
101:切換協議(Switching Protocol s)- 表示服務器正在切換協議,例如從HTTP切換到WebSocket。2xx:成功響應
200:成功(OK)- 表示請求已成功處理,并返回相應的內容。
201:已創建(Created)- 表示請求已成功處理,并在服務器上創建了新的資源。
204:無內容(No Content)- 表示請求已成功處理,但沒有返回任何內容。3xx:重定向
301:永久重定向(Moved Permanently)- 請求的資源已永久移動到新位置。
302:臨時重定向(Found)- 請求的資源臨時移動到其他位置。
304:未修改(Not Modified)- 表示客戶端的緩存資源仍有效,可以直接使用緩存的內容。4xx:客戶端錯誤
400:錯誤請求(Bad Request)- 請求無效或不可理解。
401:未授權(Unauthorized)- 請求需要身份驗證。
403 :不可訪問(Forbidden)表?訪問被拒絕.有的??通常需要??具有?定的權限才能訪問(登陸后才能訪問).如果??沒有登陸 直接訪問,就容易?到403.
404:未找到(Not Found)- 請求的資源不存在。5xx:服務器錯誤
500:服務器內部錯誤(Internal Server Error)- 服務器遇到了意外情況,無法完成請求。
503:服務不可用(Service Unavailable)- 服務器暫時無法處理請求,通常是因為過載或維護。
504:超時(GatewayTimeout) 當服務器負載?較?的時候,服務器處理單條請求的時候消耗的時間就會很?,就可能會導致出現超時 的情況.
- HTTP響應的"正文"(body)
是指服務器返回給客戶端的實際數據內容。正文通常包含了請求所需要的信息,如HTML、XML、JSON等文檔格式、圖片、音頻、視頻等二進制數據等等。
在HTTP響應中,正文通常跟隨在響應頭部分的后面,使用空行來分隔。響應頭部分包含了HTTP協議版本、狀態碼、響應頭字段等元數據信息,而正文則包含了具體的數據內容。例如,一個HTTP響應的格式通常如下所示:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1234Example Website Welcome to Example Website!
This is an example website.
cookie
客戶端請求服務器后,如果服務器需要記錄用戶狀態,服務器會在響應信息中包含一個Set-Cookie的響應頭,客戶端會根據這個響應頭存儲Cookie信息。再次請求服務器時,客戶端會在請求信息中包含一個Cookie請求頭,而服務器會根據這個請求頭進行用戶身份、狀態等較驗。
瀏覽器解析響應報文
瀏覽器解析html代碼,并請求html代碼中的資源
瀏覽器拿到html文件后,就開始解析其中的html代碼,遇到js/css/image等靜態資源時,就向服務器端去請求下載(會使用多線程下載,每個瀏覽器的線程數不一樣),這時候就用上 keep-alive(HTTP/1.1)了,建立一次HTTP連接,可以請求多個資源,下載資源的順序就是按照代碼里面的順序,但是由于每個資源大小不一樣,而瀏覽器又是多線程請求請求資源,所以這里顯示的順序并不一定是代碼里面的順序。
瀏覽器渲染
瀏覽器利用自己內部的工作機制,把請求的靜態資源和html代碼進行渲染,渲染之后呈現給用戶,瀏覽器是一個邊解析邊渲染的過程。首先瀏覽器解析HTML文件構建DOM樹,然后解析CSS文件構建渲染樹,等到渲染樹構建完成后,瀏覽器開始布局渲染樹并將其繪制到屏幕上。
這個過程比較復雜,涉及到兩個概念: reflow(回流)和repain(重繪)。DOM節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱為relow;當盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之后,瀏覽器便開始繪制內容,這個過程稱為repain。
頁面在首次加載時必然會經歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設備上,它會破壞用戶體驗,有時會造成頁面卡頓。所以我們應該盡可能少的減少reflow和repain。JS的解析是由瀏覽器中的JS解析引擎完成的。JS是單線程運行,JS有可能修改DOM結構,意味著JS執行完成前,后續所有資源的下載是沒有必要的,所以JS是單線程,會阻塞后續資源下載。