當咱們開始在瀏覽器中輸入網址的時候,瀏覽器其實就已經在智能的匹配可能的url了,他會從歷史記錄,書籤等地方,找到已經輸入的字符串可能對應的Url,而後給出智能的提示,讓你能夠補全地址。對於google的chrome的瀏覽器,他甚至會直接從緩存中把網頁展現出來,就是說,你尚未按下enter,頁面就出來了。php
1.請求一旦發起,瀏覽器首先要作的事就是解析這個域名,通常來講,瀏覽器會首先查看本地硬盤的host文件,看看其中有沒有和這個域名對應的規則,若是有的話就直接使用Hosts文件裏面的ip地址。
2.若是在本地的Hosts文件沒有可以找到對應的ip地址,瀏覽器會發出一個DNS請求到本地DNS服務器。
本地DNS服務器通常都是網絡接入服務器商提供,好比中國電信,中國移動.
3.查詢你輸入的網址的DNS請求到達本地DNS服務器以後,本地DNS服務器會首先查詢它的緩存記錄,若是緩存中有此條記錄,就能夠直接返回結果,此過程是遞歸的方式進行查詢。若是沒有緩存記錄,本地DNS服務器還要向DNS根服務器進行查詢。
4.根DNS服務器沒有記錄具體的域名和IP地址的對應關係,而是告訴本地DNS服務器,你能夠到域服務器上去繼續查詢,並給出域服務器的地址。這種過程是迭代的過程。(一層一層去找的是遞歸 | 若找了以後給你信息,讓你自已去找的是迭代)。
5.本地DNS服務器繼續向域服務器發出請求,在這個例子中,請求的對象是.com域服務器。.com域服務器收到請求以後,也不會直接返回域名和IP地址的對應關係,而是告訴本地DNS服務器,你的域名的解析服務器的地址。
6.最後,本地DNS服務器向域名的解析服務器發出請求,這時就能收到一個域名和IP地址對應關係,本地DNS服務器不只要把IP地址返回給用戶電腦,還要把這個對應關係保存在緩存中,以備此次別的用戶查詢時,能夠直接返回結果,加快網絡訪問.css
知識擴展:
什麼是DNS?
DNS(Domain Name System,域名系統),域名和IP地址相互映射的一個分佈式數據庫,可以使得用戶更加方便的訪問互聯網。而不用去記住那些能被機器讀取的IP地址串。經過主機名,最終獲得該主機名對應的IP地址的過程叫作域名解析。
通俗來講,咱們更習慣記住一個網站的名字,好比www.baidu.com而不是記住它的ip地址,好比167.23.10.2,而計算機更擅長記住網站的ip地址,而不是像www.baidu.com等連接。由於DNS就至關於一個電話本,好比你要找www.baidu.com這個域名,那我翻一翻個人電話本,就知道它167.23.10.2html
DNS查詢的兩種方式:
當局部DNS服務器自已不能回答客戶機的DNS查詢時,它就須要向其餘DNS服務器進行查詢。此時有兩種方式
1.遞歸方式
局部DNS服務器自已負頁向其餘DNS服務器進行查詢,通常是先向該域名的根域服務器查詢,再由根域名服務器一級級向下查詢,最後得的查詢結果返回給局部DNS服務器,再由局部DNS服務器返回給客戶端。web
2.迭代方式
當局部DNS服務器自已不能回答客戶機的DNS查詢時,也能夠經過迭代查詢的方式進行解析,如圖所示,局部DNS服務器不是自已向其餘DNS服務器進行查詢,而是把解析該域名的其餘DNS服務器IP地址返回給客戶端DNS程序,客戶端DNS程序再繼續向這些DNS服務器進行查詢,直到查詢到結果爲止。也就是說迭代的方式只會幫你找到相關的服務器,可是不會幫你去查。好比說:baidu.com的服務器Ip地址在192.168.4.5這裏,你自已去查吧.chrome
3.DNS域名稱空間的組織方式數據庫
4.DNS負載均衡
當一個網站有足夠多用戶的時候,假如每次請求的資源都位於同一臺主機上,那麼這臺主機隨時可能會崩掉。
處理的方案:負載均衡
原理:在DNS服務器中爲同一個主機名配置多個IP地址,在應答DNS查詢時,DNS服務器對每一個查詢將以DNS文件中主機記錄的IP地址按順序返回不一樣的解析結果,將客戶端的訪問引導到不一樣的機器上去,使得不一樣的客戶端訪問不一樣的服務器,從而達到負載均衡的目地。segmentfault
拿到域名對應的IP地址以後,瀏覽器會以一個隨機端口(1024<端口<65535)向服務器的web程序的80端口發送一個TCP的鏈接請求,這個鏈接請求到達服務器後,進入網卡,而後進入到TCP/IP協議棧(用於識別該鏈接,解封包,一層一層的剝開),還有可能要通過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序,最終創建了TCP/IP的鏈接。
創建了TCP鏈接以後,發起一個http請求,一個典型的http request header 通常須要包括請求的方法,例如get或post。後端
客戶端向服務器發起http請求時,會有一些請求信息,包含三個部分:
1.請求方法及URL協議/版本
2.請求頭(Request Header)
3.請求正文瀏覽器
完整的HTTP請求例子:緩存
GET/sample.jspHTTP/1.1 Accept:image/gif.image/jpey,*/* Accept-Language:zh-cn Connection:Keep-Alive Host:localhost User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0) Accept-Encoding:gzip,defiate username-jinqiao&password=1234
注意:最後一個請求頭以後是一個空行,發送回車和換行符,通知服務器如下再也不有請求頭。
1.請求第一行」方法URL議/版本「:GET/sample.jsp HTTP/1.1
2.請求頭(Request Header)
請求頭包含許多有關的客戶端環境和請求正文的有用信息。例如,請求頭能夠聲明瀏覽器所用的語言,請求正文的長度等
Accept:image/gif.image/jpey,*/* Accept-Language:zh-cn Connection:Keep-Alive Host:localhost User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0) Accept-Encoding:gzip,defiate
3.請求正文
請求頭和請求正文之間是一個空行,這個行很是重要,它表示請求頭已經結束,接下來是請求正文。請求正文中能夠包含客戶提交的查詢字符串信息。
username-jinqiao&password=1234
知識擴展:
TCP三次握手
第一次握手:客戶端要和服務端進行通訊,首先要告知服務端一聲,遂發出一個SYN=1的鏈接請求信號,」服務端,我想給你說說話」。
第二次握手:當服務端接收到客戶端的鏈接請求,此時要給客戶端一個確認信息,」我知道了(ACK),我這邊已經準備好了,你如今能連嗎(SYN)」。
第三次握手:當客戶端收到了服務端的確認鏈接信息後,要禮貌的告知一下服務端,「好的,我們開始聯通吧(ACK)」。
到此整個創建鏈接的過程已經結束,進入ESTABLISHED狀態,接下來就是雙方你一句我一句甚至同時交流傳遞信息的過程了.
爲何須要三次握手?
首先很是明確的是兩次握手是最基本的。第一次握手,客戶端發了個鏈接請求消息到服務端,服務端收到信息後知道本身與客戶端是能夠鏈接成功的,但此時客戶端並不知道服務端是否已經接收到了它的請求,因此服務端接收到消息後的應答,客戶端獲得服務端的反饋後,才肯定本身與服務端是能夠鏈接上的,這就是第二次握手。
客戶端只有肯定了本身能與服務端鏈接上才能開始發數據。因此兩次握手確定是最基本的。
看到這裏,你或許會問,那麼爲何須要第三次握手呢?咱們來看一下,假設一下若是沒有第三次握手,而是兩次握手後咱們就認爲鏈接成功了,那麼會發生什麼?
第三次握手是爲了防止已經失效的鏈接請求報文段忽然又傳到服務端,於是產生錯誤。
有可能有意外發生:
客戶端發出去的第一個鏈接請求因爲某些緣由在網絡節點中滯留了致使延遲,直到鏈接釋放的某個時間點纔到達服務端,這是一個早已失效的報文,可是此時服務端仍然認爲這是客戶端的創建鏈接請求第一次握手,因而服務端迴應了客戶端,第二次握手。
若是隻有兩次握手,那麼到這裏,鏈接就創建了,可是此時客戶端並無任何數據要發送,而服務端還在傻傻的等候佳音,形成很大的資源浪費。因此須要第三次握手,只有客戶端再次迴應一下,就能夠避免這種狀況。
TCP四次揮手
第一次揮手:雙方交流的差很少了,此時客戶端也已經結尾了,接下來要斷開通訊鏈接,因此告訴服務端「我說完了(FIN)」,此時自身造成等待結束鏈接的狀態。
第二次揮手:服務端知道客戶端已經沒話說了,服務端此時還有兩句內心話要給客戶端說,「我知道你說完了(ACK),我再給你說兩句,&*……%¥」。
第三次揮手:此時客戶端洗耳恭聽繼續處於等待結束的狀態,服務器端也說完了,自身此時處於等待關閉鏈接的狀態,並對告訴客戶端,「我說完了,我們斷了吧(FIN)」。
第四次揮手:客戶端收知道服務端也說完了,也要告訴服務端一聲(ACK),由於鏈接和斷開要雙方都按下關閉操做才能斷開,客戶端同時又爲本身定義一個定時器,由於不知道剛纔說的這句話能不能準確到達服務端(網絡不穩定或者其餘因素引發的網絡緣由),默認時間定爲兩個通訊的最大時間之和,超出這個時間就默認服務器端已經接收到了本身的確認信息,此時客戶端就關閉自身鏈接,服務器端一旦接收到客戶端發來的肯定通知就馬上關閉服務器端的鏈接。
到此爲止雙方整個通訊過程就此終結。這裏要聲明一下:斷開連接不必定就是客戶端,誰均可以先發起斷開指令,另外客戶端和服務端是沒有固定標準的,誰先發起請求誰就是客戶端。
爲何斷開連接的時候客戶端設置的定時器時間等待要2MSL(兩個通訊報文的最大時間)?
這個問題也很好理解,當客戶端最終告訴服務器端斷開確認的時候,他不知道本身的發出的指令是否能準確的一次性被服務器接收。假如服務器沒有接收到(這已經耗費了一個報文的最大通訊時間了),服務器端將會從新發起一個結束通話的指令(FIN)到客戶端,客戶端又接收到了服務器發來的結束通訊指令將繼續給服務器進行一個確認,有人會說那要是客戶端發出的確認信息服務端沒收到,而服務端重發的斷開指令客戶端也沒收到怎麼辦,說實話我也無奈,遇到這種狀況我們乾脆認爲網確實不行了。
爲何服務器必定要重定向而不是直接發送用戶想看的網頁內容呢?其中一個緣由跟搜索引擎排名有關。若是一個頁面有兩個地址,就像http://www.yy.com/和http://yy.com/,搜索引擎會認爲它們是兩個網站,結果形成每一個搜索連接都減小從而下降排名。而搜索引擎知道301永久重定向是什麼意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。還有就是用不一樣的地址會形成緩存友好性變差,當一個頁面有好幾個名字時,它可能會在緩存裏出現好幾回。
擴展知識
301和302的區別
301和302狀態碼都表示重定向,就是說瀏覽器在拿到服務器返回的這個狀態碼後會自動跳轉到一個新的URL地址,這個地址能夠從響應的Location首部中獲取(用戶看到的效果就是他輸入的地址A瞬間變成了另外一個地址B)——這是它們的共同點。
他們的不一樣在於。301表示舊地址A的資源已經被永久地移除了(這個資源不可訪問了),搜索引擎在抓取新內容的同時也將舊的網址交換爲重定向以後的網址;
302表示舊地址A的資源還在(仍然能夠訪問),這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址。 SEO302好於301
重定向的緣由
1.網站調整(如改變網頁目錄結構);
2.網頁被移到一個新地址;
3.網頁擴展名改變(如應用須要把.php改爲.Html或.shtml)。
這種狀況下,若是不作重定向,則用戶收藏夾或搜索引擎數據庫中舊地址只能讓訪問客戶獲得一個404頁面錯誤信息,訪問流量白白喪失;再者某些註冊了多個域名的網站,也須要經過重定向讓訪問這些域名的用戶自動跳轉到主站點等。
何時進行301或者302跳轉呢?
當一個網站或者網頁24—48小時內臨時移動到一個新的位置,這時候就要進行302跳轉,而使用301跳轉的場景就是以前的網站由於某種緣由須要移除掉,而後要到新的地址訪問,是永久性的。
清晰明確而言:使用301跳轉的大概場景以下:
一、域名到期不想續費(或者發現了更適合網站的域名),想換個域名。
二、在搜索引擎的搜索結果中出現了不帶www的域名,而帶www的域名卻沒有收錄,這個時候能夠用301重定向來告訴搜索引擎咱們目標的域名是哪個。
三、空間服務器不穩定,換空間的時候。
如今瀏覽器知道了 "http://www.google.com/"纔是要訪問的正確地址,因此它會發送另外一個http請求
通過前面的步驟,咱們終於將咱們的http請求發送到了服務器這裏,其實前面的重定向已是到達服務器了,那麼服務器是如何處理咱們的請求的。
後端從在固定的端口接收到TCP報文開始,它會對TCP鏈接進行處理,對HTTP協議進行解析,並按照報文格式進一步封裝成HTTP Request對象,供上層使用。
一些大一點的網站,會將你的請求到反向代理服務器中,由於當網站訪問量很是大,網站就愈來愈慢,一臺服務器就不夠用了,因而將同一個應用部署在多臺服務器上,將大量用戶的請求分配給多臺機器處理。此時,客戶端不是直接經過HTTP協議訪問某網站應用服務器。同時也帶來了一個好處,其中一臺服務器掛了,只要還有其餘服務器正常運行,就不會影響用戶使用。
如圖:
經過Nginx的反向代理,咱們到達了web服務器,服務端腳本處理咱們的請求,訪問咱們的數據庫,獲取須要獲取的內容。
擴展閱讀:
什麼是反向代理?
客戶端原本能夠直接經過HTTP協議訪問某網站應用服務器,網站管理員能夠在中間加上一個Nginx,客戶端請求Nginx,Nginx請求應用服務器,而後將結果返回給客戶端,此時Nginx就是反向代理服務器。
通過前面的步驟,服務器收到了咱們的請求,也處理咱們的請求,到這一步,它會把它的處理結果返回,也就是返回一個HTPP響應。
HTTP響應與HTTP請求類似,HTTP響應也由3個部分構成,分別是:
-狀態行
狀態行由協議版本、數字形式的狀態代碼、及相應的狀態描述,各元素之間以空格分隔。
格式: HTTP-Version Status-Code Reason-Phrase CRLF
例如: HTTP/1.1 200 OK rn
狀態碼
1xx:信息性狀態碼,表示服務器已接收了客戶端請求,客戶端可繼續發送請求。 100 Continue 101 Switching Protocols 2xx:成功狀態碼,表示服務器已成功接收到請求並進行處理。 200 OK 表示客戶端請求成功 204 No Content 成功,但不返回任何實體的主體部分 206 Partial Content 成功執行了一個範圍(Range)請求 3xx:重定向狀態碼,表示服務器要求客戶端重定向。 301 Moved Permanently 永久性重定向,響應報文的Location首部應該有該資源的新URL 302 Found 臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源 303 See Other 請求的資源存在着另外一個URI,客戶端應使用GET方法定向獲取請求的資源 304 Not Modified 服務器內容沒有更新,能夠直接讀取瀏覽器緩存 307 Temporary Redirect 臨時重定向。與302 Found含義同樣。302禁止POST變換爲GET,但實際使用時並不必定,307則更多瀏覽器可能會遵循這一標準,但也依賴於瀏覽器具體實現 4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。 400 Bad Request 表示客戶端請求有語法錯誤,不能被服務器所理解 401 Unauthonzed 表示請求未經受權,該狀態代碼必須與 WWW-Authenticate 報頭域一塊兒使用 403 Forbidden 表示服務器收到請求,可是拒絕提供服務,一般會在響應正文中給出不提供服務的緣由 404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL 5xx:服務器錯誤狀態碼,表示服務器未能正常處理客戶端的請求而出現意外錯誤。 500 Internel Server Error 表示服務器發生不可預期的錯誤,致使沒法完成客戶端的請求 503 Service Unavailable 表示服務器當前不可以處理客戶端的請求,在一段時間以後,服務器可能會恢復正常
-響應頭(Response Header)
由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號":"分隔,典型的響應頭有:
響應正文
包含着咱們須要的一些具體信息,好比cookie,html,image,後端返回的請求數據等等。這裏須要注意,響應正文和響應頭之間有一行空格,表示響應頭的信息到空格爲止.
HTTP/1.1 200 OK Date: Sat, 31 Dec 2005 23:59:59 GMT Content-Type: text/html;charset=ISO-8859-1 Content-Length: 122 <html> <head> <title>http</title> </head> <body> <!-- body goes here --> </body> </html>
格外備註:當文檔加載過程當中遇到js文件,html文檔會掛起渲染(加載解析渲染同步)的線程,不只要等待文檔中js文件加載完畢,還要等待解析執行完畢,才能夠恢復html文檔的渲染線程。由於JS有可能會修改DOM,最爲經典的document.write,這意味着,在JS執行完成前,後續全部資源的下載多是沒有必要的,這是js阻塞後續資源下載的根本緣由。因此我明平時的代碼中,js是放在html文檔末尾的。
其實這個步驟能夠並列在步驟8中,在瀏覽器顯示HTML時,它會注意到須要獲取其餘地址內容的標籤。這時,瀏覽器會發送一個獲取請求來從新得到這些文件。好比我要獲取外圖片,CSS,JS文件等,相似於下面的連接:
圖片:http://static.ak.fbcdn.net/rs...
CSS式樣表:http://static.ak.fbcdn.net/rs...
JavaScript 文件:http://static.ak.fbcdn.net/rs...
這些地址都要經歷一個和HTML讀取相似的過程。因此瀏覽器會在DNS中查找這些域名,發送請求,重定向等等...不像動態頁面,靜態文件會容許瀏覽器對其進行緩存。有的文件可能會不須要與服務器通信,而從緩存中直接讀取,或者能夠放到CDN中