1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        在瀏覽器地址欄輸入url到按下回車發(fā)生了什么?

        共 3491字,需瀏覽 7分鐘

         ·

        2020-11-25 02:53

        作者 |?peach
        來源 | https://juejin.cn/post/6896844956284125191
        這個問題是一個非常普遍且經(jīng)典的問題,一個合格的web程序員必須要搞懂的問題!

        詳解

        解析url

        瀏覽器通過地址欄捕獲到url地址之后,首先對url地址進行解析。url的解析如下圖所示:
        一個完整的url,包含上述幾部分,協(xié)議部分一般都是 http或者https。域名部分可以是 一段域名例如:baidu.com 也可以是 ip地址,域名最后也會被解析為ip地址。
        該ip地址的作用就是在互聯(lián)網(wǎng)中確定服務(wù)器的位置,緊接著是端口后,端口號確定的是在服務(wù)器中運行的具體的程序。路徑部分表示的是在該程序中資源的具體標識,查詢參數(shù)作用主要是為了發(fā)送數(shù)據(jù)。

        DNS解析

        一般域名都需要從運營商購買,因為ip地址不方便記憶,域名比較好記。域名都會和ip地址綁定,那么,在這里就需要做DNS解析,所謂DNS解析其實就是,根據(jù)域名找到其綁定的 ip地址。
        查找的順序如下圖:
        DNS的查找過程解析:
        1. 瀏覽器會先檢查是否存在緩存,因為如果訪問過一次該域名的話,會把結(jié)果緩存在瀏覽器中。

        2. 操作系統(tǒng)也會有自己的DNS緩存,但在這之前,會檢查域名是否存在于本地的Hosts文件中。

        3. 路由器中也會有自己的緩存。

        4. IPS DNS緩存 就是在客戶端電腦上設(shè)置的首選DNS服務(wù)器。

        5. 在前邊所有的情況下都沒有找到緩存的情況下,會連接互聯(lián)網(wǎng),把請求轉(zhuǎn)發(fā)到互聯(lián)網(wǎng)的根域。

        下圖展示了DNS的一個查詢過程

        TCP連接

        確定好目標服務(wù)器的ip地址和端口號后,就開始和遠程服務(wù)器建立TCP鏈接。三次我說的過程如下:
        • 發(fā)送方:發(fā)送消息,等待...

        • 接收方:接收消息,并給發(fā)送方回信,此時發(fā)送方接收到消息后,從發(fā)送方的角度就可明白自己的消息是可以發(fā)過去的。但是接收方還不能確定自己的消息是否可以正常發(fā)送。

        • 發(fā)送方:接收到發(fā)送方的回信后,在給接收方發(fā)一個消息,此時從接收方的角度就能明白自己的消息可以可以正常發(fā)送。

        畫成圖如下:
        TCP三次握手的好處在于的好處在于,發(fā)送方可以確認接收方仍然在線

        發(fā)送http請求

        http協(xié)議是建立在tcp/ip協(xié)議之上的,tcp保證連接通暢,http就可以正常的進行請求和響應(yīng)了。首先http請求是一個無狀態(tài)的請求,且只能由瀏覽器主動發(fā)起,服務(wù)器進行響應(yīng)。
        瀏覽器發(fā)送請求的報文會攜帶以下信息:
        • 請求路徑

        • 查詢參數(shù)

        • 請求方法

        • 請求頭

        • 請求體

        服務(wù)器接收請求

        在服務(wù)端會監(jiān)聽瀏覽器端發(fā)送的http請求,當瀏覽器的請求發(fā)出后,服務(wù)端就會接受該請求,并解析出相應(yīng)的信息,選擇對應(yīng)的邏輯進行處理(比如:查找對應(yīng)的靜態(tài)頁面,保存文件,操作數(shù)據(jù)庫,轉(zhuǎn)發(fā)....),并將處理的結(jié)果響應(yīng)給瀏覽器端。
        node服務(wù)器的一個簡單例子如下:
        const http = require('http'); // 引入http模塊
        const server = http.createServer((req, res) => { // req保存了瀏覽器攜帶的信息 // 解析出req的相關(guān)信息,比如 路徑 請求方法 請求頭 請求體等 // 編寫服務(wù)端邏輯處理代碼 // 響應(yīng) res.end();})
        server.listen(3000, () => console.log('::3000'));
        // 假設(shè)該程序巡行在 ip地址為 140.143.201.230的服務(wù)器上// 假設(shè) 140.143.201.230 綁定的域名是 www.aabbcc.com// 那么請求地址 可以為 http://www.aabbcc.com:3000/home
        // 當瀏覽器請求 http://www.aabbcc.com:3000/home之后,會DNS解析到服務(wù)器的ip地址為140.143.201.230,那么上述http.createServer接收的回調(diào)函數(shù)就會執(zhí)行。

        服務(wù)器響應(yīng)

        服務(wù)器執(zhí)行完邏輯之后,需要給瀏覽器響應(yīng)內(nèi)容(無論是要從服務(wù)器獲取數(shù)據(jù),還是在服務(wù)器做了什么操作,都需要給瀏覽器一個響應(yīng))
        響應(yīng)一般包含以下幾部分
        • 狀態(tài)碼

        • 狀態(tài)文本

        • 響應(yīng)頭

        • 響應(yīng)體

        服務(wù)器響應(yīng)的同時肯定會伴隨著瀏覽器端接收,等瀏覽器端徹底接收完畢之后,TCP就要進行4次揮手,并斷開連接了。

        TCP鏈接斷開

        TCP鏈接的斷開需要經(jīng)過"四次揮手",那么就需要一方主動的釋放另外一方被動的釋放。大體的過程如下:
        1. 瀏覽器端發(fā)消息通知服務(wù)器現(xiàn)在需要斷開(第一次揮手)

        2. 服務(wù)器接到要斷開的請求之后,給瀏覽器返回消息,告訴瀏覽器我正在準備釋放(第二次揮手)

        3. 此時瀏覽器接到消息后正在等待服務(wù)器釋放完成,而服務(wù)器正在準備釋放的過程

        4. 當服務(wù)器釋放完成后,再通知瀏覽器我已經(jīng)釋放完成了。(第三次揮手)

        5. 瀏覽器接收到服務(wù)器釋放完成的消息后,再給服務(wù)器發(fā)送消息告訴服務(wù)器我已經(jīng)知道你釋放完成了,服務(wù)器收到消息后,就能確認自己釋放完成的消息已經(jīng)通知到了(第四次揮手)

        瀏覽器解析資源

        當瀏覽器接收到服務(wù)器響應(yīng)的資源后,會對資源進行解析。
        1. 首先,查看Response Header,根據(jù)響應(yīng)頭的指示做不同的事情,比如重定向,存儲cookie,解壓gzip,緩存資源等等。

        2. 接下來獲取MIME類型(查看響應(yīng)頭的 Content-Type的值),根據(jù)不同的資源類型采用不同的解析方式

        渲染頁面

        一般來說從地址欄輸入地址后,絕大多是情況下響應(yīng)的都是 html文件,那么就說以說頁面是如何渲染html頁面的,html頁面中一般也會嵌入css,js,圖片等資源。
        因此如果解析到這些資源的時候,會再次向目標服務(wù)器發(fā)起請求,那么又會經(jīng)歷從解析url地址開始的各個步驟。
        整個頁面的加載如下圖所示:

        html頁面的加載

        首先要知道瀏覽器解析是從上往下一行一行地解析的。
        1. 解碼:傳輸回來的其實都是一些二進制字節(jié)數(shù)據(jù),瀏覽器需要根據(jù)文件指定編碼(例如UTF-8)轉(zhuǎn)換成字符串,也就是HTML 代碼
        2. 預(yù)解析:預(yù)解析做的事情是提前加載資源,減少處理時間,它會識別一些會請求資源的屬性,比如img標簽的src屬性,并將這個請求加到請求隊列中。
        3. 符號化:符號化是詞法分析的過程,將輸入解析成符號,HTML 符號包括,開始標簽、結(jié)束標簽、屬性名和屬性值。它通過一個狀態(tài)機去識別符號的狀態(tài),比如遇到<,>狀態(tài)都會產(chǎn)生變化。
        4. 構(gòu)建樹:在上一步符號化中,解析器獲得這些標記,然后以合適的方法創(chuàng)建DOM對象并把這些符號插入到DOM對象中。
        瀏覽器的容錯機制:你從來沒有在瀏覽器看過類似”語法無效”的錯誤,這是因為瀏覽器去糾正錯誤的語法,然后繼續(xù)工作。

        CSS解析

        一旦瀏覽器下載了 CSS,CSS 解析器就會處理它遇到的任何 CSS,根據(jù)語法規(guī)范解析出所有的 CSS 并進行標記化,然后我們得到一個規(guī)則表。
        在匹配一個節(jié)點對應(yīng)的 CSS 規(guī)則時,是按照從右到左的順序的,例如:div p { font-size :14px }會先尋找所有的p標簽然后判斷它的父元素是否為div。
        所以我們寫 CSS 時,盡量用 id 和 class,千萬不要過度層疊。

        javaScript編譯執(zhí)行

        大致流程如下:
        主要是三個階段
        1. 詞法分析:js腳本加載完畢后,會首先進入語法分析階段,它首先會分析代碼塊的語法是否正確,不正確則拋出“語法錯誤”,停止執(zhí)行。

        2. 預(yù)編譯:js有三種運行環(huán)境分別是 全局環(huán)境,函數(shù)環(huán)境,eval。每進入一個不同的運行環(huán)境都會創(chuàng)建一個對應(yīng)的執(zhí)行上下文,根據(jù)不同的上下文環(huán)境,形成一個函數(shù)調(diào)用棧,棧底永遠是全局執(zhí)行上下文,棧頂則永遠是當前執(zhí)行上下文。

        3. 執(zhí)行:js雖然是單線程的,但是實際參與工作的線程一共有四個:JS引擎線程(主),事件觸發(fā)線程,定時器觸發(fā)線程,HTTP異步請求線程

        總結(jié)

        從瀏覽地地址欄輸入地址按下回車,可以看做是一次請求的發(fā)起,那么必然會經(jīng)歷以下幾個步驟:
        1. 解析url地址

        2. DNS解析

        3. TCP鏈接

        4. 發(fā)送http請求

        5. 服務(wù)器接收請求

        6. 服務(wù)器響應(yīng)

        7. TCP鏈接斷開

        8. 瀏覽器解析資源

        那么我們需要明白,瀏覽器可以發(fā)送請求的方式不止地址欄輸入地址這一種。比如a標簽,img,link,script,form表單,ajax,fetch等等,這些方式都可以發(fā)出http請求,那么他們都會經(jīng)歷上述的過程,最終拿到資源,只是拿到資源的類型不一樣,那么瀏覽器的處理方式也不一樣。
        本文完~
        瀏覽 34
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            色秘 乱码一区二区三区mba | 欧美大鸡巴操逼 | 91n-最新地址发布页 | 天天日天天射天天舔 | 中文字幕人妻一区二区三区免费 | 日韩无日韩在线 | 印度肥妇bbw快交 | 91精品久久香蕉国产线看 | 国内精品国产成人三级 | 日韩免费黄片 |