我們平時(shí)在瀏覽網(wǎng)頁(yè)的時(shí)候都是使用瀏覽器,輸入你要的網(wǎng)址后回車(chē),就會(huì)顯示出我們所想要的內(nèi)容,看似這個(gè)簡(jiǎn)單的用戶操作行為的背后,Web的工作原理是怎樣的呢?到底隱藏了些什么呢?
對(duì)于傳統(tǒng)的上網(wǎng)流程,系統(tǒng)它是這么做的:瀏覽器本身它是一個(gè)客戶端,當(dāng)輸入U(xiǎn)RL地址的時(shí)候,瀏覽器首先會(huì)去請(qǐng)求DNS服務(wù)器,通過(guò)DNS查詢獲取相應(yīng)的域名所對(duì)應(yīng)的IP地址,然后通過(guò)這個(gè)映射的IP地址找到IP對(duì)應(yīng)的服務(wù)器,并建立連接,等瀏覽器發(fā)送完HTTP Request(請(qǐng)求)包后,服務(wù)器接收到請(qǐng)求包之后才開(kāi)始處理,返回HTTP Response(響應(yīng))包,客戶端瀏覽器收到來(lái)自服務(wù)器的響應(yīng)后就開(kāi)始渲染這個(gè)Response包里的主體(body)部分,等收到全部的內(nèi)容后斷開(kāi)與該服務(wù)器之間的連接。
一個(gè)Web服務(wù)器也被稱為HTTP服務(wù)器,它通過(guò)HTTP協(xié)議與客戶端通信。這個(gè)客戶端通常指的是Web瀏覽器(其實(shí)手機(jī)端客戶端內(nèi)部也是瀏覽器實(shí)現(xiàn)的)。
1 |
客戶機(jī)通過(guò)TCP/IP協(xié)議建立到服務(wù)器的TCP連接 |
2 |
客戶端向服務(wù)器發(fā)送HTTP協(xié)議請(qǐng)求包,請(qǐng)求服務(wù)器里的資源文檔 |
3 |
服務(wù)器向客戶機(jī)發(fā)送HTTP協(xié)議應(yīng)答包,如果請(qǐng)求的資源包含有動(dòng)態(tài)語(yǔ)言的內(nèi)容,那么服務(wù)器會(huì)調(diào)用動(dòng)態(tài)語(yǔ)言的解釋引擎負(fù)責(zé)處理“動(dòng)態(tài)內(nèi)容”,并將處理得到的數(shù)據(jù)返回給客戶端 |
4 |
客戶機(jī)與服務(wù)器斷開(kāi)。由客戶端解釋HTML文檔,在客戶端屏幕上渲染圖形結(jié)果 |
一個(gè)簡(jiǎn)單的HTTP事務(wù)就是這樣實(shí)現(xiàn)的,看起來(lái)很復(fù)雜,原理其實(shí)是挺簡(jiǎn)單的。需要注意的是客戶機(jī)與服務(wù)器之間的通信是非持久連接的,也就是當(dāng)服務(wù)器發(fā)送了應(yīng)答后就與客戶機(jī)斷開(kāi)連接,等待下一次請(qǐng)求。
我們?yōu)g覽網(wǎng)頁(yè)都是通過(guò)URL訪問(wèn)的,那么URL到底是怎么樣的呢?
URL(Uniform Resource Locator)是“統(tǒng)一資源定位符”的英文縮寫(xiě),用于描述一個(gè)網(wǎng)絡(luò)上的資源, 基本格式如下:
scheme://host[:port#]/path/.../[?query-string][#anchor]
scheme |
指定低層使用的協(xié)議(例如:http, https, ftp) |
host |
HTTP服務(wù)器的IP地址或者域名 |
port |
HTTP服務(wù)器的默認(rèn)端口是80,這種情況下端口號(hào)可以省略。如果使用了別的端口,必須指明,例如 http://www.qixing318.com:80/ |
path |
訪問(wèn)資源的路徑 |
query-string |
發(fā)送給http服務(wù)器的數(shù)據(jù) |
anchor |
錨 |
DNS(Domain Name System)是“域名系統(tǒng)”的英文縮寫(xiě),是一種組織成域?qū)哟谓Y(jié)構(gòu)的計(jì)算機(jī)和網(wǎng)絡(luò)服務(wù)命名系統(tǒng),它用于TCP/IP網(wǎng)絡(luò),它從事將主機(jī)名或域名轉(zhuǎn)換為實(shí)際IP地址的工作。DNS就是這樣的一位“翻譯官”,它的基本工作原理可用下圖來(lái)表示。
更詳細(xì)的DNS解析的過(guò)程如下,這個(gè)過(guò)程有助于我們理解DNS的工作模式
1 |
在瀏覽器中輸入www.qq.com域名,操作系統(tǒng)會(huì)先檢查自己本地的hosts文件是否有這個(gè)網(wǎng)址映射關(guān)系,如果有,就先調(diào)用這個(gè)IP地址映射,完成域名解析。 |
2 |
如果hosts里沒(méi)有這個(gè)域名的映射,則查找本地DNS解析器緩存,是否有這個(gè)網(wǎng)址映射關(guān)系,如果有,直接返回,完成域名解析。 |
3 |
如果hosts與本地DNS解析器緩存都沒(méi)有相應(yīng)的網(wǎng)址映射關(guān)系,首先會(huì)找TCP/IP參數(shù)中設(shè)置的首選DNS服務(wù)器,在此我們叫它本地DNS服務(wù)器,此服務(wù)器收到查詢時(shí),如果要查詢的域名,包含在本地配置區(qū)域資源中,則返回解析結(jié)果給客戶機(jī),完成域名解析,此解析具有權(quán)威性。 |
4 |
如果要查詢的域名,不由本地DNS服務(wù)器區(qū)域解析,但該服務(wù)器已緩存了此網(wǎng)址映射關(guān)系,則調(diào)用這個(gè)IP地址映射,完成域名解析,此解析不具有權(quán)威性。 |
5 |
如果本地DNS服務(wù)器本地區(qū)域文件與緩存解析都失效,則根據(jù)本地DNS服務(wù)器的設(shè)置(是否設(shè)置轉(zhuǎn)發(fā)器)進(jìn)行查詢,如果未用轉(zhuǎn)發(fā)模式,本地DNS就把請(qǐng)求發(fā)至 “根DNS服務(wù)器”,“根DNS服務(wù)器”收到請(qǐng)求后會(huì)判斷這個(gè)域名(.com)是誰(shuí)來(lái)授權(quán)管理,并會(huì)返回一個(gè)負(fù)責(zé)該頂級(jí)域名服務(wù)器的一個(gè)IP。本地DNS服務(wù)器收到IP信息后,將會(huì)聯(lián)系負(fù)責(zé).com域的這臺(tái)服務(wù)器。這臺(tái)負(fù)責(zé).com域的服務(wù)器收到請(qǐng)求后,如果自己無(wú)法解析,它就會(huì)找一個(gè)管理.com域的下一級(jí)DNS服務(wù)器地址(qixing318.com)給本地DNS服務(wù)器。當(dāng)本地DNS服務(wù)器收到這個(gè)地址后,就會(huì)找qixing318.com域服務(wù)器,重復(fù)上面的動(dòng)作,進(jìn)行查詢,直至找到www.qixing318.com主機(jī)。 |
6 |
如果用的是轉(zhuǎn)發(fā)模式,此DNS服務(wù)器就會(huì)把請(qǐng)求轉(zhuǎn)發(fā)至上一級(jí)DNS服務(wù)器,由上一級(jí)服務(wù)器進(jìn)行解析,上一級(jí)服務(wù)器如果不能解析,或找根DNS或把轉(zhuǎn)請(qǐng)求轉(zhuǎn)至上上級(jí),以此循環(huán)。不管是本地DNS服務(wù)器用是是轉(zhuǎn)發(fā),還是根提示,最后都是把結(jié)果返回給本地DNS服務(wù)器,由此DNS服務(wù)器再返回給客戶機(jī)。 |
所謂 遞歸查詢過(guò)程 就是 “查詢的遞交者” 更替, 而 迭代查詢過(guò)程 則是 “查詢的遞交者”不變。
舉個(gè)例子來(lái)說(shuō),你想知道某個(gè)一起上法律課的女孩的電話,并且你偷偷拍了她的照片,回到寢室告訴一個(gè)很仗義的哥們兒,這個(gè)哥們兒二話沒(méi)說(shuō),拍著胸脯告訴你,甭急,我替你查(此處完成了一次遞歸查詢,即,問(wèn)詢者的角色更替)。然后他拿著照片問(wèn)了學(xué)院大四學(xué)長(zhǎng),學(xué)長(zhǎng)告訴他,這姑娘是xx系的;然后這哥們兒馬不停蹄又問(wèn)了xx系的辦公室主任助理同學(xué),助理同學(xué)說(shuō)是xx系yy班的,然后很仗義的哥們兒去xx系yy班的班長(zhǎng)那里取到了該女孩兒電話。(此處完成若干次迭代查詢,即,問(wèn)詢者角色不變,但反復(fù)更替問(wèn)詢對(duì)象)最后,他把號(hào)碼交到了你手里。完成整個(gè)查詢過(guò)程。
通過(guò)上面的步驟,我們最后獲取的是IP地址,也就是瀏覽器最后發(fā)起請(qǐng)求的時(shí)候是基于IP來(lái)和服務(wù)器做信息交互的。
HTTP協(xié)議是Web工作的核心,所以要了解清楚Web的工作方式就需要詳細(xì)的了解清楚HTTP是怎么樣工作的。
HTTP是一種讓W(xué)eb服務(wù)器與瀏覽器(客戶端)通過(guò)Internet發(fā)送與接收數(shù)據(jù)的協(xié)議,它建立在TCP協(xié)議之上,一般采用TCP的80端口。它是一個(gè)請(qǐng)求、響應(yīng)協(xié)議--客戶端發(fā)出一個(gè)請(qǐng)求,服務(wù)器響應(yīng)這個(gè)請(qǐng)求。
在HTTP中,客戶端總是通過(guò)建立一個(gè)連接與發(fā)送一個(gè)HTTP請(qǐng)求來(lái)發(fā)起一個(gè)事務(wù)。服務(wù)器不能主動(dòng)去與客戶端聯(lián)系,也不能給客戶端發(fā)出一個(gè)回調(diào)連接??蛻舳伺c服務(wù)器端都可以提前中斷一個(gè)連接。例如,當(dāng)瀏覽器下載一個(gè)文件時(shí),你可以通過(guò)點(diǎn)擊“停止”鍵來(lái)中斷文件的下載,關(guān)閉與服務(wù)器的HTTP連接。
HTTP協(xié)議是無(wú)狀態(tài)的,同一個(gè)客戶端的這次請(qǐng)求和上次請(qǐng)求是沒(méi)有對(duì)應(yīng)關(guān)系,對(duì)HTTP服務(wù)器來(lái)說(shuō),它并不知道這兩個(gè)請(qǐng)求是否來(lái)自同一個(gè)客戶端。為了解決這個(gè)問(wèn)題, Web程序引入了Cookie機(jī)制來(lái)維護(hù)連接的可持續(xù)狀態(tài)。
HTTP協(xié)議是建立在TCP協(xié)議之上的,因此TCP攻擊一樣會(huì)影響HTTP的通訊,例如比較常見(jiàn)的一些攻擊:SYN Flood是當(dāng)前最流行的DoS(拒絕服務(wù)攻擊)與DdoS(分布式拒絕服務(wù)攻擊)的方式之一,這是一種利用TCP協(xié)議缺陷,發(fā)送大量偽造的TCP連接請(qǐng)求,從而使得被攻擊方資源耗盡(CPU滿負(fù)荷或內(nèi)存不足)的攻擊方式。
我們先來(lái)看看Request包的結(jié)構(gòu), Request包分為3部分,第一部分叫Request line(請(qǐng)求行), 第二部分叫Request header(請(qǐng)求頭),第三部分是body(主體)。
header和body之間有個(gè)空行,請(qǐng)求包的例子所示:
GET /domains/example/ HTTP/1.1 |
請(qǐng)求行: 請(qǐng)求方法 請(qǐng)求URI HTTP協(xié)議/協(xié)議版本 |
Host:www.qixing318.com. |
服務(wù)端的主機(jī)名 |
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4 |
客戶端瀏覽器信息 |
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
客戶端能接收的mine類型 |
Accept-Encoding:gzip,deflate,sdcn |
是否支持流壓縮 |
Accept-Charset:UTF-8,*;q=0.5 |
客戶端字符編碼集 |
"\r\n\r\n" |
空行,用于分割請(qǐng)求頭和消息體 |
"\r\n\r\n" |
空行,消息體,請(qǐng)求資源參數(shù),例如POST傳遞的參數(shù) |
HTTP協(xié)議定義了很多與服務(wù)器交互的請(qǐng)求方法,最基本的有4種,分別是GET,POST,PUT,DELETE。一個(gè)URL地址用于描述一個(gè)網(wǎng)絡(luò)上的資源,而HTTP中的GET, POST, PUT, DELETE就對(duì)應(yīng)著對(duì)這個(gè)資源的查,改,增,刪4個(gè)操作。我們最常見(jiàn)的就是GET和POST了。GET一般用于獲取/查詢資源信息,而POST一般用于更新資源信息。
上圖為:fiddler抓取的GET信息
上圖為:fiddler抓取的POST信息
1 |
我們可以看到GET請(qǐng)求消息體為空,POST請(qǐng)求帶有消息體。 |
2 |
GET提交的數(shù)據(jù)會(huì)放在URL之后,以?分割URL和傳輸數(shù)據(jù),參數(shù)之間以&相連,如EditPosts.aspx?name=test1&id=123456。POST方法是把提交的數(shù)據(jù)放在HTTP包的body中。 |
3 |
GET提交的數(shù)據(jù)大小有限制(因?yàn)闉g覽器對(duì)URL的長(zhǎng)度有限制),而POST方法提交的數(shù)據(jù)沒(méi)有限制。 |
4 |
GET方式提交數(shù)據(jù),會(huì)帶來(lái)安全問(wèn)題,比如一個(gè)登錄頁(yè)面,通過(guò)GET方式提交數(shù)據(jù)時(shí),用戶名和密碼將出現(xiàn)在URL上,如果頁(yè)面可以被緩存或者其他人可以訪問(wèn)這臺(tái)機(jī)器,就可以從歷史記錄獲得該用戶的賬號(hào)和密碼。 |
我們?cè)賮?lái)看看HTTP的response包,他的結(jié)構(gòu)如下:
HTTP/1.1 200 OK |
狀態(tài)行 |
Server: nginx/1.0.8 |
服務(wù)器使用的WEB軟件名及版本 |
Date:Date: Tue, 30 Oct 2012 04:14:25 GMT |
發(fā)送時(shí)間 |
Content-Type: text/html |
服務(wù)器發(fā)送信息的類型 |
Transfer-Encoding: chunked |
表示發(fā)送HTTP包是分段發(fā)的 |
Connection: keep-alive |
保持連接狀態(tài) |
Content-Length: 90 |
消息主體內(nèi)容長(zhǎng)度 |
\r\n |
空行,用來(lái)分割消息頭和主體 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... |
消息體部分 |
Response包中的第一行叫做狀態(tài)行,由HTTP協(xié)議版本號(hào), 狀態(tài)碼, 狀態(tài)消息 三部分組成。
狀態(tài)碼用來(lái)告訴HTTP客戶端,HTTP服務(wù)器是否產(chǎn)生了預(yù)期的Response。
HTTP/1.1協(xié)議中定義了5類狀態(tài)碼, 狀態(tài)碼由三位數(shù)字組成,第一個(gè)數(shù)字定義了響應(yīng)的類別
1XX |
提示信息 - 表示請(qǐng)求已被成功接收,繼續(xù)處理 |
2XX |
成功 - 表示請(qǐng)求已被成功接收,理解,接受 |
3XX |
重定向 - 要完成請(qǐng)求必須進(jìn)行更進(jìn)一步的處理 |
4XX |
客戶端錯(cuò)誤 - 請(qǐng)求有語(yǔ)法錯(cuò)誤或請(qǐng)求無(wú)法實(shí)現(xiàn) |
5XX |
服務(wù)器端錯(cuò)誤 - 服務(wù)器未能實(shí)現(xiàn)合法的請(qǐng)求 |
我們看下面這個(gè)圖展示了詳細(xì)的返回信息,左邊可以看到有很多的資源返回碼,200是常用的,表示正常信息,302表示跳轉(zhuǎn)。response header里面展示了詳細(xì)的信息。
【上圖:訪問(wèn)一次網(wǎng)站的全部請(qǐng)求信息】
無(wú)狀態(tài)是指協(xié)議對(duì)于事務(wù)處理沒(méi)有記憶能力,服務(wù)器不知道客戶端是什么狀態(tài)。從另一方面講,打開(kāi)一個(gè)服務(wù)器上的網(wǎng)頁(yè)和你之前打開(kāi)這個(gè)服務(wù)器上的網(wǎng)頁(yè)之間沒(méi)有任何聯(lián)系。
HTTP是一個(gè)無(wú)狀態(tài)的面向連接的協(xié)議,無(wú)狀態(tài)不代表HTTP不能保持TCP連接,更不能代表HTTP使用的是UDP協(xié)議(面對(duì)無(wú)連接)。
從HTTP/1.1起,默認(rèn)都開(kāi)啟了Keep-Alive保持連接特性,簡(jiǎn)單地說(shuō),當(dāng)一個(gè)網(wǎng)頁(yè)打開(kāi)完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會(huì)關(guān)閉,如果客戶端再次訪問(wèn)這個(gè)服務(wù)器上的網(wǎng)頁(yè),會(huì)繼續(xù)使用這一條已經(jīng)建立的TCP連接。
Keep-Alive不會(huì)永久保持連接,它有一個(gè)保持時(shí)間,可以在不同服務(wù)器軟件(如Apache)中設(shè)置這個(gè)時(shí)間。
【上圖為:一次請(qǐng)求的request和response】
上面這張圖我們可以了解到整個(gè)的通訊過(guò)程,同時(shí)細(xì)心的讀者是否注意到了一點(diǎn),一個(gè)URL請(qǐng)求但是左邊欄里面為什么會(huì)有那么多的資源請(qǐng)求(這些都是靜態(tài)文件,go對(duì)于靜態(tài)文件有專門(mén)的處理方式)。
這個(gè)就是瀏覽器的一個(gè)功能,第一次請(qǐng)求url,服務(wù)器端返回的是html頁(yè)面,然后瀏覽器開(kāi)始渲染HTML:當(dāng)解析到HTML DOM里面的圖片連接,css腳本和js腳本的鏈接,瀏覽器就會(huì)自動(dòng)發(fā)起一個(gè)請(qǐng)求靜態(tài)資源的HTTP請(qǐng)求,獲取相對(duì)應(yīng)的靜態(tài)資源,然后瀏覽器就會(huì)渲染出來(lái),最終將所有資源整合、渲染,完整展現(xiàn)在我們面前的屏幕上。
網(wǎng)頁(yè)優(yōu)化方面有一項(xiàng)措施是減少HTTP請(qǐng)求次數(shù),就是把盡量多的css和js資源合并在一起,目的是盡量減少網(wǎng)頁(yè)請(qǐng)求靜態(tài)資源的次數(shù),提高網(wǎng)頁(yè)加載速度,同時(shí)減緩服務(wù)器的壓力。
聯(lián)系客服