聲明:本文章中的說(shuō)法僅是個(gè)人理解總結(jié)禾进,不一定完全正確豁跑,但是可以有助于理解。
關(guān)于HTTP協(xié)議可以參考以下:
HTTP協(xié)議漫談 http://kb.cnblogs.com/page/140611/HTTP協(xié)議概覽 http://www.cnblogs.com/vamei/archive/2013/05/11/3069788.html了解HTTP Headers的方方面面 http://kb.cnblogs.com/page/55442/
當(dāng)我們?cè)跒g覽器的地址欄輸入 www.linux178.com 泻云,然后回車艇拍,回車這一瞬間到看到頁(yè)面到底發(fā)生了什么呢?
域名解析 --> 發(fā)起TCP的3次握手 --> 建立TCP連接后發(fā)起http請(qǐng)求 --> 服務(wù)器響應(yīng)http請(qǐng)求宠纯,瀏覽器得到html代碼 --> 瀏覽器解析html代碼卸夕,并請(qǐng)求html代碼中的資源(如js、css婆瓜、圖片等) --> 瀏覽器對(duì)頁(yè)面進(jìn)行渲染呈現(xiàn)給用戶
以下就是上面過程的一一分析快集,我們就以Chrome瀏覽器為例:
一.域名解析
首先Chrome瀏覽器會(huì)解析 www.linux178.com 這個(gè)域名(準(zhǔn)確的叫法應(yīng)該是主機(jī)名)對(duì)應(yīng)的IP地址。怎么解析到對(duì)應(yīng)的IP地址廉白?
(1).Chrome瀏覽器 會(huì)首先搜索瀏覽器自身的DNS緩存(緩存時(shí)間比較短个初,大概只有1分鐘,且只能容納1000條緩存)猴蹂,看自身的緩存中是否有www.linux178.com 對(duì)應(yīng)的條目院溺,而且沒有過期,如果有且沒有過期則解析到此結(jié)束磅轻。 注:我們?cè)趺床榭碈hrome自身的緩存覆获?可以使用 chrome://net-internals/#dns 來(lái)進(jìn)行查看
(2).如果瀏覽器自身的緩存里面沒有找到對(duì)應(yīng)的條目,那么Chrome會(huì)搜索操作系統(tǒng)自身的DNS緩存,如果找到且沒有過期則停止搜索解析到此結(jié)束. 注:怎么查看操作系統(tǒng)自身的DNS緩存瓢省,以Windows系統(tǒng)為例弄息,可以在命令行下使用 ipconfig /displaydns 來(lái)進(jìn)行查看
(3). 如果在Windows系統(tǒng)的DNS緩存也沒有找到,那么嘗試讀取hosts文件(位于C:\Windows\System32\drivers\etc)勤婚,看看這里面有沒有該域名對(duì)應(yīng)的IP地址摹量,如果有則解析成功。
(4). 如果在hosts文件中也沒有找到對(duì)應(yīng)的條目馒胆,瀏覽器就會(huì)發(fā)起一個(gè)DNS的系統(tǒng)調(diào)用缨称,就會(huì)向本地配置的首選DNS服務(wù)器(一般是電信運(yùn)營(yíng)商提供的,也可以使用像Google提供的DNS服務(wù)器)發(fā)起域名解析請(qǐng)求(通過的是UDP協(xié)議向DNS的53端口發(fā)起請(qǐng)求祝迂,這個(gè)請(qǐng)求是遞歸的請(qǐng)求睦尽,也就是運(yùn)營(yíng)商的DNS服務(wù)器必須得提供給我們?cè)撚蛎腎P地址),運(yùn)營(yíng)商的DNS服務(wù)器首先查找自身的緩存型雳,找到對(duì)應(yīng)的條目当凡,且沒有過期山害,則解析成功。如果沒有找到對(duì)應(yīng)的條目沿量,則有運(yùn)營(yíng)商的DNS代我們的瀏覽器發(fā)起迭代DNS解析請(qǐng)求浪慌,它首先是會(huì)找根域的DNS的IP地址(這個(gè)DNS服務(wù)器都內(nèi)置13臺(tái)根域的DNS的IP地址),找打根域的DNS地址朴则,就會(huì)向其發(fā)起請(qǐng)求(請(qǐng)問www.linux178.com這個(gè)域名的IP地址是多少叭ㄏ恕?)乌妒,根域發(fā)現(xiàn)這是一個(gè)頂級(jí)域com域的一個(gè)域名汹想,于是就告訴運(yùn)營(yíng)商的DNS我不知道這個(gè)域名的IP地址,但是我知道com域的IP地址撤蚊,你去找它去欧宜,于是運(yùn)營(yíng)商的DNS就得到了com域的IP地址,又向com域的IP地址發(fā)起了請(qǐng)求(請(qǐng)問www.linux178.com這個(gè)域名的IP地址是多少?),com域這臺(tái)服務(wù)器告訴運(yùn)營(yíng)商的DNS我不知道www.linux178.com這個(gè)域名的IP地址拴魄,但是我知道linux178.com這個(gè)域的DNS地址冗茸,你去找它去,于是運(yùn)營(yíng)商的DNS又向linux178.com這個(gè)域名的DNS地址(這個(gè)一般就是由域名注冊(cè)商提供的匹中,像萬(wàn)網(wǎng)夏漱,新網(wǎng)等)發(fā)起請(qǐng)求(請(qǐng)問www.linux178.com這個(gè)域名的IP地址是多少?)顶捷,這個(gè)時(shí)候linux178.com域的DNS服務(wù)器一查挂绰,誒,果真在我這里服赎,于是就把找到的結(jié)果發(fā)送給運(yùn)營(yíng)商的DNS服務(wù)器葵蒂,這個(gè)時(shí)候運(yùn)營(yíng)商的DNS服務(wù)器就拿到了www.linux178.com這個(gè)域名對(duì)應(yīng)的IP地址,并返回給Windows系統(tǒng)內(nèi)核重虑,內(nèi)核又把結(jié)果返回給瀏覽器践付,終于瀏覽器拿到了www.linux178.com對(duì)應(yīng)的IP地址,該進(jìn)行一步的動(dòng)作了缺厉。注:一般情況下是不會(huì)進(jìn)行以下步驟的如果經(jīng)過以上的4個(gè)步驟永高,還沒有解析成功,那么會(huì)進(jìn)行如下步驟:5 操作系統(tǒng)就會(huì)查找NetBIOS name Cache(NetBIOS名稱緩存提针,就存在客戶端電腦中的)命爬,那這個(gè)緩存有什么東西呢?凡是最近一段時(shí)間內(nèi)和我成功通訊的計(jì)算機(jī)的計(jì)算機(jī)名和Ip地址辐脖,就都會(huì)存在這個(gè)緩存里面饲宛。什么情況下該步能解析成功呢?就是該名稱正好是幾分鐘前和我成功通信過嗜价,那么這一步就可以成功解析艇抠。6 如果第5步也沒有成功幕庐,那會(huì)查詢WINS 服務(wù)器(是NETBIOS名稱和IP地址對(duì)應(yīng)的服務(wù)器)7 如果第6步也沒有查詢成功,那么客戶端就要進(jìn)行廣播查找8 如果第7步也沒有成功练链,那么客戶端就讀取LMHOSTS文件(和HOSTS文件同一個(gè)目錄下翔脱,寫法也一樣)如果第八步還沒有解析成功奴拦,那么就宣告這次解析失敗媒鼓,那就無(wú)法跟目標(biāo)計(jì)算機(jī)進(jìn)行通信。只要這八步中有一步可以解析成功错妖,那就可以成功和目標(biāo)計(jì)算機(jī)進(jìn)行通信绿鸣。
看下圖抓包截圖:Linux虛擬機(jī)測(cè)試,使用命令 wget www.linux178.com 來(lái)請(qǐng)求暂氯,發(fā)現(xiàn)直接使用chrome瀏覽器請(qǐng)求時(shí)潮模,干擾請(qǐng)求比較多,所以就使用wget命令來(lái)請(qǐng)求痴施,不過使用wget命令只能把index.html請(qǐng)求回來(lái)擎厢,并不會(huì)對(duì)index.html中包含的靜態(tài)資源(js、css等文件)進(jìn)行請(qǐng)求辣吃。
抓包分析:
1 號(hào)包动遭,這個(gè)是那臺(tái)虛擬機(jī)在廣播,要獲取192.168.100.254(也就是網(wǎng)關(guān))的MAC地址神得,因?yàn)榫钟蚓W(wǎng)的通信靠的是MAC地址厘惦,它為什么需要跟網(wǎng)關(guān)進(jìn)行通信是因?yàn)槲覀兊腄NS服務(wù)器IP是外圍IP,要出去必須要依靠網(wǎng)關(guān)幫我們出去才行哩簿。2 號(hào)包宵蕉,這個(gè)是網(wǎng)關(guān)收到了虛擬機(jī)的廣播之后,回應(yīng)給虛擬機(jī)的回應(yīng)节榜,告訴虛擬機(jī)自己的MAC地址羡玛,于是客戶端找到了路由出口。3 號(hào)包宗苍,這個(gè)包是wget命令向系統(tǒng)配置的DNS服務(wù)器提出域名解析請(qǐng)求(準(zhǔn)確的說(shuō)應(yīng)該是wget發(fā)起了一個(gè)DNS解析的系統(tǒng)調(diào)用)缝左,請(qǐng)求的域名www.linux178.com,期望得到的是IP6的地址(AAAA代表的是IPv6地址)4 號(hào)包,這個(gè)DNS服務(wù)器給系統(tǒng)的響應(yīng)浓若,很顯然目前使用IPv6的還是極少數(shù)渺杉,所以得不到AAAA記錄的5 號(hào)包,這個(gè)還是請(qǐng)求解析IPv6地址挪钓,但是www.linu.com.leo.com這個(gè)主機(jī)名是不存在的是越,所以得到結(jié)果就是no such name6 號(hào)包,這個(gè)才是請(qǐng)求的域名對(duì)應(yīng)的IPv4地址(A記錄)7 號(hào)包碌上,DNS服務(wù)器不管是從緩存里面倚评,還是進(jìn)行迭代查詢最終得到了域名的IP地址浦徊,響應(yīng)給了系統(tǒng),系統(tǒng)再給了wget命令天梧,wget于是得到了www.linux178.com的IP地址盔性,這里也可以看出客戶端和本地的DNS服務(wù)器是遞歸的查詢(也就是服務(wù)器必須給客戶端一個(gè)結(jié)果)這就可以開始下一步了,進(jìn)行TCP的三次握手呢岗。
二.發(fā)起TCP的3次握手
拿到域名對(duì)應(yīng)的IP地址之后冕香,User-Agent(一般是指瀏覽器)會(huì)以一個(gè)隨機(jī)端口(1024 < 端口 < 65535)向服務(wù)器的WEB程序(常用的有httpd,nginx等)80端口發(fā)起TCP的連接請(qǐng)求。這個(gè)連接請(qǐng)求(原始的http請(qǐng)求經(jīng)過TCP/IP4層模型的層層封包)到達(dá)服務(wù)器端后(這中間通過各種路由設(shè)備后豫,局域網(wǎng)內(nèi)除外)悉尾,進(jìn)入到網(wǎng)卡,然后是進(jìn)入到內(nèi)核的TCP/IP協(xié)議棧(用于識(shí)別該連接請(qǐng)求挫酿,解封包构眯,一層一層的剝開),還有可能要經(jīng)過Netfilter防火墻(屬于內(nèi)核的模塊)的過濾早龟,最終到達(dá)WEB程序(本文就以Nginx為例)惫霸,最終建立了TCP/IP的連接。
1) Client首先發(fā)送一個(gè)連接試探葱弟,ACK=0 表示確認(rèn)號(hào)無(wú)效壹店,SYN = 1 表示這是一個(gè)連接請(qǐng)求或連接接受報(bào)文,同時(shí)表示這個(gè)數(shù)據(jù)報(bào)不能攜帶數(shù)據(jù)翘悉,seq = x 表示Client自己的初始序號(hào)(seq = 0 就代表這是第0號(hào)包)茫打,這時(shí)候Client進(jìn)入syn_sent狀態(tài),表示客戶端等待服務(wù)器的回復(fù)2) Server監(jiān)聽到連接請(qǐng)求報(bào)文后妖混,如同意建立連接老赤,則向Client發(fā)送確認(rèn)。TCP報(bào)文首部中的SYN 和 ACK都置1 制市,ack = x + 1表示期望收到對(duì)方下一個(gè)報(bào)文段的第一個(gè)數(shù)據(jù)字節(jié)序號(hào)是x+1抬旺,同時(shí)表明x為止的所有數(shù)據(jù)都已正確收到(ack=1其實(shí)是ack=0+1,也就是期望客戶端的第1個(gè)包),seq = y 表示Server 自己的初始序號(hào)(seq=0就代表這是服務(wù)器這邊發(fā)出的第0號(hào)包)祥楣。這時(shí)服務(wù)器進(jìn)入syn_rcvd开财,表示服務(wù)器已經(jīng)收到Client的連接請(qǐng)求,等待client的確認(rèn)误褪。3) Client收到確認(rèn)后還需再次發(fā)送確認(rèn)责鳍,同時(shí)攜帶要發(fā)送給Server的數(shù)據(jù)。ACK 置1 表示確認(rèn)號(hào)ack= y + 1 有效(代表期望收到服務(wù)器的第1個(gè)包)兽间,Client自己的序號(hào)seq= x + 1(表示這就是我的第1個(gè)包历葛,相對(duì)于第0個(gè)包來(lái)說(shuō)的),一旦收到Client的確認(rèn)之后嘀略,這個(gè)TCP連接就進(jìn)入Established狀態(tài)恤溶,就可以發(fā)起http請(qǐng)求了乓诽。
看抓包截圖:
9 號(hào)包 這個(gè)就是對(duì)應(yīng)上面的步驟 1)10 號(hào)包 這個(gè)對(duì)應(yīng)的上面的步驟 2)11 號(hào)包 這個(gè)對(duì)應(yīng)的上面的步驟 3)
TCP 為什么需要3次握手?
舉個(gè)例子:
假設(shè)一個(gè)老外在故宮里面迷路了咒程,看到了小明鸠天,于是就有下面的對(duì)話:
老外: Excuse me,Can you Speak English?小明: yes 帐姻。老外: OK,I want ...
在問路之前稠集,老外先問小明是否會(huì)說(shuō)英語(yǔ),小明回答是的卖宠,這時(shí)老外才開始問路
2個(gè)計(jì)算機(jī)通信是靠協(xié)議(目前流行的TCP/IP協(xié)議)來(lái)實(shí)現(xiàn),如果2個(gè)計(jì)算機(jī)使用的協(xié)議不一樣巍杈,那是不能進(jìn)行通信的忧饭,所以這個(gè)3次握手就相當(dāng)于試探一下對(duì)方是否遵循TCP/IP協(xié)議扛伍,協(xié)商完成后就可以進(jìn)行通信了,當(dāng)然這樣理解不是那么準(zhǔn)確词裤。
為什么HTTP協(xié)議要基于TCP來(lái)實(shí)現(xiàn)刺洒?
目前在Internet中所有的傳輸都是通過TCP/IP進(jìn)行的,HTTP協(xié)議作為TCP/IP模型中應(yīng)用層的協(xié)議也不例外吼砂,TCP是一個(gè)端到端的可靠的面向連接的協(xié)議逆航,所以HTTP基于傳輸層TCP協(xié)議不用擔(dān)心數(shù)據(jù)的傳輸?shù)母鞣N問題。
三.建立TCP連接后發(fā)起http請(qǐng)求
進(jìn)過TCP3次握手之后渔肩,瀏覽器發(fā)起了http的請(qǐng)求(看第?包)因俐,使用的http的方法 GET 方法,請(qǐng)求的URL是 / ,協(xié)議是HTTP/1.0
下面是第12號(hào)包的詳細(xì)內(nèi)容:
以上的報(bào)文是HTTP請(qǐng)求報(bào)文周偎。
那么HTTP請(qǐng)求報(bào)文和響應(yīng)報(bào)文會(huì)是什么格式呢抹剩?
起始行:如 GET / HTTP/1.0 (請(qǐng)求的方法 請(qǐng)求的URL 請(qǐng)求所使用的協(xié)議)頭部信息:User-Agent Host等成對(duì)出現(xiàn)的值主體
不管是請(qǐng)求報(bào)文還是響應(yīng)報(bào)文都會(huì)遵循以上的格式。
那么起始行中的請(qǐng)求方法有哪些種呢蓉坎?
GET: 完整請(qǐng)求一個(gè)資源 (常用)HEAD: 僅請(qǐng)求響應(yīng)首部POST:提交表單 (常用)PUT: (webdav) 上傳 DELETE:(webdav) 刪除 OPTIONS:返回請(qǐng)求的資源所支持的方法的方法 TRACE: 追求一個(gè)資源請(qǐng)求中間所經(jīng)過的代理
那什么是URL澳眷、URI、URN蛉艾?
URI Uniform Resource Identifier 統(tǒng)一資源標(biāo)識(shí)符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暫時(shí)都通指一個(gè)東西
請(qǐng)求的協(xié)議有哪些種钳踊?
有以下幾種:
http/0.9: statelesshttp/1.0: MIME, keep-alive (保持連接), 緩存http/1.1: 更多的請(qǐng)求方法,更精細(xì)的緩存控制勿侯,持久連接(persistent connection) 比較常用
下面是Chrome發(fā)起的http請(qǐng)求報(bào)文頭部信息
其中
Accept 就是告訴服務(wù)器端拓瞪,我接受那些MIME類型Accept-Encoding 這個(gè)看起來(lái)是接受那些壓縮方式的文件Accept-Lanague 告訴服務(wù)器能夠發(fā)送哪些語(yǔ)言 Connection 告訴服務(wù)器支持keep-alive特性Cookie 每次請(qǐng)求時(shí)都會(huì)攜帶上Cookie以方便服務(wù)器端識(shí)別是否是同一個(gè)客戶端Host 用來(lái)標(biāo)識(shí)請(qǐng)求服務(wù)器上的那個(gè)虛擬主機(jī),比如Nginx里面可以定義很多個(gè)虛擬主機(jī) 那這里就是用來(lái)標(biāo)識(shí)要訪問那個(gè)虛擬主機(jī)助琐。User-Agent 用戶代理祭埂,一般情況是瀏覽器,也有其他類型弓柱,如:wget curl 搜索引擎的蜘蛛等 條件請(qǐng)求首部:If-Modified-Since 是瀏覽器向服務(wù)器端詢問某個(gè)資源文件如果自從什么時(shí)間修改過沟堡,那么重新發(fā)給我侧但,這樣就保證服務(wù)器端資源 文件更新時(shí),瀏覽器再次去請(qǐng)求航罗,而不是使用緩存中的文件安全請(qǐng)求首部:Authorization: 客戶端提供給服務(wù)器的認(rèn)證信息禀横;
什么是MIME?
MIME(Multipurpose Internet Mail Extesions 多用途互聯(lián)網(wǎng)郵件擴(kuò)展)是一個(gè)互聯(lián)網(wǎng)標(biāo)準(zhǔn)粥血,它擴(kuò)展了電子郵件標(biāo)準(zhǔn)柏锄,使其能夠支持非ASCII字符、二進(jìn)制格式附件等多種格式的郵件消息复亏,這個(gè)標(biāo)準(zhǔn)被定義在RFC 2045趾娃、RFC 2046、RFC 2047缔御、RFC 2048抬闷、RFC 2049等RFC中。 由RFC 822轉(zhuǎn)變而來(lái)的RFC 2822耕突,規(guī)定電子郵件標(biāo)準(zhǔn)并不允許在郵件消息中使用7位ASCII字符集以外的字符笤成。正因如此,一些非英語(yǔ)字符消息和二進(jìn)制文件眷茁,圖像炕泳,聲音等非文字消息都不能在電子郵件中傳輸。MIME規(guī)定了用于表示各種各樣的數(shù)據(jù)類型的符號(hào)化方法上祈。 此外培遵,在萬(wàn)維網(wǎng)中使用的HTTP協(xié)議中也使用了MIME的框架,標(biāo)準(zhǔn)被擴(kuò)展為互聯(lián)網(wǎng)媒體類型登刺。
MIME 遵循以下格式:major/minor 主類型/次類型 例如:
image/jpgimage/giftext/htmlvideo/quicktimeappliation/x-httpd-php
四.服務(wù)器端響應(yīng)http請(qǐng)求籽腕,瀏覽器得到html代碼
看下圖 第12號(hào)包是http請(qǐng)求包,第32包是http響應(yīng)包
服務(wù)器端WEB程序接收到http請(qǐng)求以后塘砸,就開始處理該請(qǐng)求节仿,處理之后就返回給瀏覽器html文件。
第32號(hào)包 是服務(wù)器返回給客戶端http響應(yīng)包(200 ok 響應(yīng)的MIME類型是text/html)掉蔬,代表這一次客戶端發(fā)起的http請(qǐng)求已成功響應(yīng)廊宪。200 代表是的 響應(yīng)成功的狀態(tài)碼,還有其他的狀態(tài)碼如下:
1xx: 信息性狀態(tài)碼 100, 1012xx: 成功狀態(tài)碼 200:OK3xx: 重定向狀態(tài)碼 301: 永久重定向, Location響應(yīng)首部的值仍為當(dāng)前URL女轿,因此為隱藏重定向; 302: 臨時(shí)重定向箭启,顯式重定向, Location響應(yīng)首部的值為新的URL 304:Not Modified 未修改,比如本地緩存的資源文件和服務(wù)器上比較時(shí)蛉迹,發(fā)現(xiàn)并沒有修改傅寡,服務(wù)器返回一個(gè)304狀態(tài)碼, 告訴瀏覽器,你不用請(qǐng)求該資源荐操,直接使用本地的資源即可芜抒。4xx: 客戶端錯(cuò)誤狀態(tài)碼 404: Not Found 請(qǐng)求的URL資源并不存在5xx: 服務(wù)器端錯(cuò)誤狀態(tài)碼 500: Internal Server Error 服務(wù)器內(nèi)部錯(cuò)誤 502: Bad Gateway 前面代理服務(wù)器聯(lián)系不到后端的服務(wù)器時(shí)出現(xiàn) 504:Gateway Timeout 這個(gè)是代理能聯(lián)系到后端的服務(wù)器,但是后端的服務(wù)器在規(guī)定的時(shí)間內(nèi)沒有給代理服務(wù)器響應(yīng)
用Chrome瀏覽器看到的響應(yīng)頭信息:
Connection 使用keep-alive特性Content-Encoding 使用gzip方式對(duì)資源壓縮Content-type MIME類型為html類型托启,字符集是 UTF-8Date 響應(yīng)的日期Server 使用的WEB服務(wù)器Transfer-Encoding:chunked 分塊傳輸編碼 是http中的一種數(shù)據(jù)傳輸機(jī)制宅倒,允許HTTP由網(wǎng)頁(yè)服務(wù)器發(fā)送給客戶端應(yīng)用(通常是網(wǎng)頁(yè)瀏覽器)的數(shù)據(jù)可以分成多個(gè)部分,分塊傳輸編碼只在HTTP協(xié)議1.1版本(HTTP/1.1)中提供Vary 這個(gè)可以參考(http://blog.csdn.net/tenfyguo/article/details/5939000)X-Pingback 參考(http://blog.sina.com.cn/s/blog_bb80041c0101fmfz.html)
那到底服務(wù)器端接收到http請(qǐng)求后是怎么樣生成html文件屯耸?
假設(shè)服務(wù)器端使用nginx+php(fastcgi)架構(gòu)提供服務(wù)
1 nginx讀取配置文件
我們?cè)跒g覽器的地址欄里面輸入的是 http://www.linux178.com (http://可以不用輸入拐迁,瀏覽器會(huì)自動(dòng)幫我們添加),其實(shí)完整的應(yīng)該是http://www.linux178.com./ 后面還有個(gè)點(diǎn)(這個(gè)點(diǎn)代表就是根域疗绣,一般情況下我們不用輸入线召,也不顯示),后面的/也是不用添加,瀏覽器會(huì)自動(dòng)幫我們添加(且看第3部那個(gè)圖里面的URL)多矮,那么實(shí)際請(qǐng)求的URL是http://www.linux178.com/缓淹,那么好了Nginx在收到 瀏覽器 GET / 請(qǐng)求時(shí),會(huì)讀取http請(qǐng)求里面的頭部信息工窍,根據(jù)Host來(lái)匹配 自己的所有的虛擬主機(jī)的配置文件的server_name,看看有沒有匹配的割卖,有匹配那么就讀取該虛擬主機(jī)的配置前酿,發(fā)現(xiàn)如下配置:
root /web/echo
通過這個(gè)就知道所有網(wǎng)頁(yè)文件的就在這個(gè)目錄下 這個(gè)目錄就是/ 當(dāng)我們http://www.linux178.com/時(shí)就是訪問這個(gè)目錄下面的文件患雏,例如訪問http://www.linux178.com/index.html,那么代表/web/echo下面有個(gè)文件叫index.html
index index.html index.htm index.php
通過這個(gè)就能得知網(wǎng)站的首頁(yè)文件是那個(gè)文件,也就是我們?cè)谌?a target="_blank" rel="nofollow">http://www.linux178.com/ 罢维,nginx就會(huì)自動(dòng)幫我們把index.html(假設(shè)首頁(yè)是index.php 當(dāng)然是會(huì)嘗試的去找到該文件淹仑,如果沒有找到該文件就依次往下找,如果這3個(gè)文件都沒有找到肺孵,那么就拋出一個(gè)404錯(cuò)誤)加到后面匀借,那么添加之后的URL是/index.php,然后根據(jù)后面的配置進(jìn)行處理
location ~ ..php(/.)*$ { root /web/echo; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; astcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params;}
這一段配置指明凡是請(qǐng)求的URL中匹配(這里是啟用了正則表達(dá)式進(jìn)行匹配) *.php后綴的(后面跟的參數(shù))都交給后端的fastcgi進(jìn)程進(jìn)行處理。
2 把php文件交給fastcgi進(jìn)程去處理
于是nginx把/index.php這個(gè)URL交給了后端的fastcgi進(jìn)程處理平窘,等待fastcgi處理完成后(結(jié)合數(shù)據(jù)庫(kù)查詢出數(shù)據(jù)吓肋,填充模板生成html文件)返回給nginx一個(gè)index.html文檔,Nginx再把這個(gè)index.html返回給瀏覽器瑰艘,于是乎瀏覽器就拿到了首頁(yè)的html代碼是鬼,同時(shí)nginx寫一條訪問日志到日志文件中去。
注1:nginx是怎么找index.php文件的紫新?
當(dāng)nginx發(fā)現(xiàn)需要/web/echo/index.php文件時(shí)均蜜,就會(huì)向內(nèi)核發(fā)起IO系統(tǒng)調(diào)用(因?yàn)橐布蚪坏溃@里的硬件是指硬盤芒率,通常需要靠?jī)?nèi)核來(lái)操作囤耳,而內(nèi)核提供的這些功能是通過系統(tǒng)調(diào)用來(lái)實(shí)現(xiàn)的),告訴內(nèi)核,我需要這個(gè)文件,內(nèi)核從/開始找到web目錄充择,再在web目錄下找到echo目錄德玫,最后在echo目錄下找到index.php文件,于是把這個(gè)index.php從硬盤上讀取到內(nèi)核自身的內(nèi)存空間椎麦,然后再把這個(gè)文件復(fù)制到nginx進(jìn)程所在的內(nèi)存空間化焕,于是乎nginx就得到了自己想要的文件了。
注2:尋找文件在文件系統(tǒng)層面是怎么操作的铃剔?
比如nginx需要得到/web/echo/index.php這個(gè)文件
每個(gè)分區(qū)(像ext3 ext3等文件系統(tǒng)撒桨,block塊是文件存儲(chǔ)的最小單元 默認(rèn)是4096字節(jié))都是包含元數(shù)據(jù)區(qū)和數(shù)據(jù)區(qū),每一個(gè)文件在元數(shù)據(jù)區(qū)都有元數(shù)據(jù)條目(一般是128字節(jié)大屑怠)凤类,每一個(gè)條目都有一個(gè)編號(hào),我們稱之為inode(index node 索引節(jié)點(diǎn))普气,這個(gè)inode里面包含 文件類型谜疤、權(quán)限、連接次數(shù)现诀、屬主和數(shù)組的ID夷磕、時(shí)間戳、這個(gè)文件占據(jù)了那些磁盤塊也就是塊的編號(hào)(block仔沿,每個(gè)文件可以占用多個(gè)block,并且block不一定是連續(xù)的坐桩,每個(gè)block是有編號(hào)的),如下圖所示:
還有一個(gè)要點(diǎn):目錄其實(shí)也普通是文件封锉,也需要占用磁盤塊绵跷,目錄不是一個(gè)容器。你看默認(rèn)創(chuàng)建的目錄就是4096字節(jié)成福,也就說(shuō)只需要占用一個(gè)磁盤塊碾局,但這是不確定的。所以要找到目錄也是需要到元數(shù)據(jù)區(qū)里面找到對(duì)應(yīng)的條目奴艾,只有找到對(duì)應(yīng)的inode就可找到目錄所占用的磁盤塊净当。
那到底目錄里面存放著什么,難道不是文件或者其他目錄嗎蕴潦?
其實(shí)目錄存著這么一張表(姑且這么理解)像啼,里面放著 目錄或者文件的名稱和對(duì)應(yīng)的inode號(hào)(暫時(shí)稱之為映射表),如下圖:
假設(shè)
/ 在數(shù)據(jù)區(qū)占據(jù) 1、2號(hào)block 品擎,/其實(shí)也是一個(gè)目錄 里面有3個(gè)目錄 web 111web 占據(jù) 5號(hào)block 是目錄 里面有2個(gè)目錄 echo dataecho 占據(jù) 11號(hào) block 是目錄 里面有1個(gè)文件 index.phpindex.php 占據(jù) 15 16號(hào) block 是文件
其在文件系統(tǒng)中分布如下圖所示
那么內(nèi)核究竟是怎么找到index.php這個(gè)文件的呢埋合?
內(nèi)核拿到nginx的IO系統(tǒng)調(diào)用要獲取/web/echo/index.php這個(gè)文件請(qǐng)求之后
1 內(nèi)核讀取元數(shù)據(jù)區(qū) / 的inode,從inode里面讀取/所對(duì)應(yīng)的數(shù)據(jù)塊的編號(hào)萄传,然后在數(shù)據(jù)區(qū)找到其對(duì)應(yīng)的塊(1 2號(hào)塊)甚颂,讀取1號(hào)塊上的映射表找到web這個(gè)名稱在元數(shù)據(jù)區(qū)對(duì)應(yīng)的inode號(hào)2 內(nèi)核讀取web對(duì)應(yīng)的inode(3號(hào))蜜猾,從中得知web在數(shù)據(jù)區(qū)對(duì)應(yīng)的塊是5號(hào)塊,于是到數(shù)據(jù)區(qū)找到5號(hào)塊振诬,從中讀取映射表蹭睡,知道echo對(duì)應(yīng)的inode是5號(hào),于是到元數(shù)據(jù)區(qū)找到5號(hào)inode3 內(nèi)核讀取5號(hào)inode赶么,得到echo在數(shù)據(jù)區(qū)對(duì)應(yīng)的是11號(hào)塊肩豁,于是到數(shù)據(jù)區(qū)讀取11號(hào)塊得到映射表,得到index.php對(duì)應(yīng)的inode是9號(hào)4 內(nèi)核到元數(shù)據(jù)區(qū)讀取9號(hào)inode辫呻,得到index.php對(duì)應(yīng)的是15和16號(hào)數(shù)據(jù)塊清钥,于是就到數(shù)據(jù)區(qū)域找到15 16號(hào)塊,讀取其中的內(nèi)容放闺,得到index.php的完整內(nèi)容
五. 瀏覽器解析html代碼祟昭,并請(qǐng)求html代碼中的資源
瀏覽器拿到index.html文件后,就開始解析其中的html代碼怖侦,遇到j(luò)s/css/image等靜態(tài)資源時(shí)篡悟,就向服務(wù)器端去請(qǐng)求下載(會(huì)使用多線程下載,每個(gè)瀏覽器的線程數(shù)不一樣)匾寝,這個(gè)時(shí)候就用上keep-alive特性了搬葬,建立一次HTTP連接,可以請(qǐng)求多個(gè)資源艳悔,下載資源的順序就是按照代碼里的順序急凰,但是由于每個(gè)資源大小不一樣,而瀏覽器又多線程請(qǐng)求請(qǐng)求資源很钓,所以從下圖看出香府,這里顯示的順序并不一定是代碼里面的順序。
瀏覽器在請(qǐng)求靜態(tài)資源時(shí)(在未過期的情況下)码倦,向服務(wù)器端發(fā)起一個(gè)http請(qǐng)求(詢問自從上一次修改時(shí)間到現(xiàn)在有沒有對(duì)資源進(jìn)行修改),如果服務(wù)器端返回304狀態(tài)碼(告訴瀏覽器服務(wù)器端沒有修改)锭碳,那么瀏覽器會(huì)直接讀取本地的該資源的緩存文件袁稽。
詳細(xì)的瀏覽器工作原理請(qǐng)看:http://kb.cnblogs.com/page/129756/
六.瀏覽器對(duì)頁(yè)面進(jìn)行渲染呈現(xiàn)給用戶
最后,瀏覽器利用自己內(nèi)部的工作機(jī)制擒抛,把請(qǐng)求到的靜態(tài)資源和html代碼進(jìn)行渲染推汽,渲染之后呈現(xiàn)給用戶。
自此一次完整的HTTP事務(wù)宣告完成.