一次完整的瀏覽器請求流程
當(dāng)我們在瀏覽器的地址欄輸入 www.linux178.com ,然后回車,回車這一瞬間到看到頁面到底發(fā)生了什么呢?
整個流程如下:
- 域名解析 -->
- 發(fā)起TCP的3次握手 -->
- 建立TCP連接后發(fā)起http請求 -->
- 服務(wù)器響應(yīng)http請求,瀏覽器得到html代碼 -->
- 瀏覽器解析html代碼,并請求html代碼中的資源(如js、css、圖片等) -->
- 瀏覽器對頁面進(jìn)行渲染呈現(xiàn)給用戶
以下就是上面過程的一一分析,我們就以Chrome瀏覽器為例:
域名解析
首先Chrome瀏覽器會解析 www.linux178.com 這個域名對應(yīng)的IP地址。怎么解析到對應(yīng)的IP地址?
Chrome瀏覽器會首先搜索瀏覽器自身的DNS緩存(緩存時間比較短,大概只有1分鐘,且只能容納1000條緩存)。
如果瀏覽器自身緩存找不到則會查看系統(tǒng)的DNS緩存,如果找到且沒有過期則停止搜索解析到此結(jié)束.
而如果本機(jī)沒有找到DNS緩存,則瀏覽器會發(fā)起一個DNS的系統(tǒng)調(diào)用,就會向本地配置的首選DNS服務(wù)器發(fā)起域名解析請求(通過的是UDP協(xié)議向DNS的53端口發(fā)起請求,這個請求是遞歸的請求,也就是運營商的DNS服務(wù)器必須得提供給我們該域名的IP地址),運營商的DNS服務(wù)器首先查找自身的緩存,找到對應(yīng)的條目,且沒有過期,則解析成功。如果沒有找到對應(yīng)的條目,則有運營商的DNS代我們的瀏覽器發(fā)起迭代DNS解析請求,它首先是會找根域的DNS的IP地址(這個DNS服務(wù)器都內(nèi)置13臺根域的DNS的IP地址),找打根域的DNS地址,就會向其發(fā)起請求(請問www.linux178.com這個域名的IP地址是多少?。浚?,根域發(fā)現(xiàn)這是一個頂級域com域的一個域名,于是就告訴運營商的DNS我不知道這個域名的IP地址,但是我知道com域的IP地址,你去找它去,于是運營商的DNS就得到了com域的IP地址,又向com域的IP地址發(fā)起了請求(請問www.linux178.com這個域名的IP地址是多少?),com域這臺服務(wù)器告訴運營商的DNS我不知道www.linux178.com這個域名的IP地址,但是我知道linux178.com這個域的DNS地址,你去找它去,于是運營商的DNS又向linux178.com這個域名的DNS地址(這個一般就是由域名注冊商提供的,像萬網(wǎng),新網(wǎng)等)發(fā)起請求(請問www.linux178.com這個域名的IP地址是多少?),這個時候linux178.com域的DNS服務(wù)器一查,誒,果真在我這里,于是就把找到的結(jié)果發(fā)送給運營商的DNS服務(wù)器,這個時候運營商的DNS服務(wù)器就拿到了www.linux178.com這個域名對應(yīng)的IP地址,并返回給Windows系統(tǒng)內(nèi)核,內(nèi)核又把結(jié)果返回給瀏覽器,終于瀏覽器拿到了www.linux178.com對應(yīng)的IP地址,該進(jìn)行一步的動作了。
發(fā)起TCP的3次握手
拿到域名對應(yīng)的IP地址之后,User-Agent(一般是指瀏覽器)會以一個隨機(jī)端口(1024< 端口 < 65535)向服務(wù)器的WEB程序(常用的有httpd,nginx等)80端口發(fā)起TCP的連接請求。這個連接請求(原始的http請求經(jīng)過TCP/IP4層模型的層層封包)到達(dá)服務(wù)器端后(這中間通過各種路由設(shè)備,局域網(wǎng)內(nèi)除外),進(jìn)入到網(wǎng)卡,然后是進(jìn)入到內(nèi)核的TCP/IP協(xié)議棧(用于識別該連接請求,解封包,一層一層的剝開),還有可能要經(jīng)過Netfilter防火墻(屬于內(nèi)核的模塊)的過濾,最終到達(dá)WEB程序(本文就以Nginx為例),最終建立了TCP/IP的連接。
為什么HTTP協(xié)議要基于TCP來實現(xiàn)?
TCP是一個端到端的可靠的面向連接的協(xié)議,所以HTTP基于傳輸層TCP協(xié)議不用擔(dān)心數(shù)據(jù)的傳輸?shù)母鞣N問題。
建立TCP連接后發(fā)起http請求
進(jìn)過TCP3次握手之后,瀏覽器發(fā)起了http的請求,使用的http的方法 GET 方法,請求的URL是 / ,協(xié)議是HTTP/1.0
下面是第12號包的詳細(xì)內(nèi)容:

以上的報文是HTTP請求報文。
那么HTTP請求報文和響應(yīng)報文會是什么格式呢?
個HTTP請求報文由請求行(request line),請求頭部(header),
空行和請求數(shù)據(jù)4個部分組成,下圖給出了請求報文的一般格式。
請求行
請求行由請求方法字段、URL字段和HTTP協(xié)議版本字段3個字段組成,它們用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP協(xié)議的請求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。這里介紹最常用的GET方法和POST方法。
- GET:當(dāng)客戶端要從服務(wù)器中讀取文檔時,使用GET方法。GET方法要求服務(wù)器將URL定位的資源放在響應(yīng)報文的數(shù)據(jù)部分,回送給客戶端。使用GET方法時,請求參數(shù)和對應(yīng)的值附加在URL后面,利用一個問號(“?”)代表URL的結(jié)尾與請求參數(shù)的開始,傳遞參數(shù)長度受限制。例如,/index.jsp?id=100&op=bind。
- POST:當(dāng)客戶端給服務(wù)器提供信息較多時可以使用POST方法。POST方法將請求參數(shù)封裝在HTTP請求數(shù)據(jù)中,以名稱/值的形式出現(xiàn),可以傳輸大量數(shù)據(jù)。
請求頭部
請求頭部由關(guān)鍵字/值對組成,每行一對,關(guān)鍵字和值用英文冒號“:”分隔。請求頭部通知服務(wù)器有關(guān)于客戶端請求的信息,典型的請求頭有:
User-Agent:產(chǎn)生請求的瀏覽器類型。
Accept:客戶端可識別的內(nèi)容類型列表。
Host:請求的主機(jī)名,允許多個域名同處一個IP地址,即虛擬主機(jī)。
空行
最后一個請求頭之后是一個空行,發(fā)送回車符和換行符,通知服務(wù)器以下不再有請求頭。
請求數(shù)據(jù)
請求數(shù)據(jù)不在GET方法中使用,而是在POST方法中使用。POST方法適用于需要客戶填寫表單的場合。與請求數(shù)據(jù)相關(guān)的最常使用的請求頭是Content-Type和Content-Length。
那么起始行中的請求方法有哪些種呢?
GET: 完整請求一個資源 (常用)
HEAD: 僅請求響應(yīng)首部
POST:提交表單 (常用)
PUT: 上傳
DELETE:刪除
那什么是URL、URI、URN?
URI Uniform Resource Identifier 統(tǒng)一資源標(biāo)識符
URL Uniform Resource Locator 統(tǒng)一資源定位符 格式如下: scheme://[username:password@]HOST:port/path/to/source http://www.magedu.com/downloads/nginx-1.5.tar.gzURN Uniform Resource Name 統(tǒng)一資源名稱URL和URN 都屬于 URI為了方便就把URL和URI暫時都通指一個東西
請求的協(xié)議有哪些種?
有以下幾種:
http/0.9: statelesshttp/1.0: MIME, keep-alive (保持連接), 緩存http/1.1: 更多的請求方法,更精細(xì)的緩存控制,持久連接(persistent connection) 比較常用
下面是Chrome發(fā)起的http請求報文頭部信息

其中
Accept 就是告訴服務(wù)器端,我接受那些MIME類型Accept-Encoding 這個看起來是接受那些壓縮方式的文件Accept-Lanague 告訴服務(wù)器能夠發(fā)送哪些語言 Connection 告訴服務(wù)器支持keep-alive特性Cookie 每次請求時都會攜帶上Cookie以方便服務(wù)器端識別是否是同一個客戶端Host 用來標(biāo)識請求服務(wù)器上的那個虛擬主機(jī),比如Nginx里面可以定義很多個虛擬主機(jī) 那這里就是用來標(biāo)識要訪問那個虛擬主機(jī)。User-Agent 用戶代理,一般情況是瀏覽器,也有其他類型,如:wget curl 搜索引擎的蜘蛛等 條件請求首部:If-Modified-Since 是瀏覽器向服務(wù)器端詢問某個資源文件如果自從什么時間修改過,那么重新發(fā)給我,這樣就保證服務(wù)器端資源 文件更新時,瀏覽器再次去請求,而不是使用緩存中的文件安全請求首部:Authorization: 客戶端提供給服務(wù)器的認(rèn)證信息;
服務(wù)器端響應(yīng)http請求,瀏覽器得到html代碼
服務(wù)器端WEB程序接收到http請求以后,就開始處理該請求,處理之后就返回給瀏覽器html文件。

第32號包 是服務(wù)器返回給客戶端http響應(yīng)包(200 ok 響應(yīng)的MIME類型是text/html),代表這一次客戶端發(fā)起的http請求已成功響應(yīng)。200 代表是的 響應(yīng)成功的狀態(tài)碼,還有其他的狀態(tài)碼如下:
1xx: 信息性狀態(tài)碼 100, 101
2xx: 成功狀態(tài)碼 200:OK
3xx: 重定向狀態(tài)碼
301: 永久重定向, Location響應(yīng)首部的值仍為當(dāng)前URL,因此為隱藏重定向;
302: 臨時重定向,顯式重定向, Location響應(yīng)首部的值為新的URL
304:Not Modified 未修改,比如本地緩存的資源文件和服務(wù)器上比較時,發(fā)現(xiàn)并沒有修改,服務(wù)器返回一個304狀態(tài)碼, 告訴瀏覽器,你不用請求該資源,直接使用本地的資源即可。
4xx: 客戶端錯誤狀態(tài)碼
404: Not Found 請求的URL資源并不存在
5xx: 服務(wù)器端錯誤狀態(tài)碼
500: Internal Server Error 服務(wù)器內(nèi)部錯誤
502: Bad Gateway 前面代理服務(wù)器聯(lián)系不到后端的服務(wù)器時出現(xiàn)
504:Gateway Timeout 這個是代理能聯(lián)系到后端的服務(wù)器,但是后端的服務(wù)器在規(guī)定的時間內(nèi)沒有給代理服務(wù)器響應(yīng)
瀏覽器解析html代碼,并請求html代碼中的資源
瀏覽器拿到index.html文件后,就開始解析其中的html代碼,遇到j(luò)s/css/image等靜態(tài)資源時,就向服務(wù)器端去請求下載(會使用多線程下載,每個瀏覽器的線程數(shù)不一樣),這個時候就用上keep-alive特性了,建立一次HTTP連接,可以請求多個資源。
瀏覽器在請求靜態(tài)資源時(在未過期的情況下),向服務(wù)器端發(fā)起一個http請求(詢問自從上一次修改時間到現(xiàn)在有沒有對資源進(jìn)行修改),如果服務(wù)器端返回304狀態(tài)碼(告訴瀏覽器服務(wù)器端沒有修改),那么瀏覽器會直接讀取本地的該資源的緩存文件。

瀏覽器對頁面進(jìn)行渲染呈現(xiàn)給用戶
最后,瀏覽器利用自己內(nèi)部的工作機(jī)制,把請求到的靜態(tài)資源和html代碼進(jìn)行渲染,渲染之后呈現(xiàn)給用戶。