非常好的文章声搁,怕博主刪除黑竞,再也找不到這么好的文章了,所以復制了一份疏旨,博主是2016年寫很魂,但是是到現(xiàn)在為止看到的,思路清晰充石,主題鮮明的一篇好文章莫换,特轉發(fā)下:http://www.reibang.com/p/558455228c43
WEB請求處理一:瀏覽器請求發(fā)起處理
最近霞玄,終于要把《WEB請求處理系列》提上日程了骤铃,一直答應小伙伴們給分享一套完整的WEB請求處理流程:從瀏覽器、Nginx坷剧、Servlet容器惰爬,最終到應用程序WEB請求的一個處理流程,前段時間由于其他工作事情的安排惫企,一直未進行整理撕瞧。不過還好該系列終于啟動了陵叽,給大家分享的同時,也順便整理下自己的思路丛版,以便溫故而知新吧巩掺。希望大家都能在此過程中得到新的收獲吧。
本系列主要分五部分:
1.《WEB請求處理一:瀏覽器請求發(fā)起處理》:分析用戶在瀏覽器中輸入URL地址页畦,瀏覽器如何找到服務器地址的過程胖替,并發(fā)起請求;
2.《WEB請求處理二:Nginx請求反向代理》:分析請求在達反向代理服務器內部處理過程豫缨;
3.《WEB請求處理三:Servlet容器請求處理》:分析請求在Servlet容器內部處理過程独令,并找到目標應用程序;
4.《WEB請求處理四:WEB MVC框架請求處理》:分析請求在應用程序內部好芭,開源MVC框架的處理過程燃箭;
5.《WEB請求處理五:瀏覽器請求響應處理》:分析請求在服務器端處理完成后,瀏覽器渲染響應頁面過程舍败;
為直觀明了招狸,先上一張圖,紅色部分為本章所述模塊:
本章所述模塊
1 B/S網(wǎng)絡架構概述#
我們先了解下B/S網(wǎng)絡架構是什么邻薯?B/S網(wǎng)絡架構從前端到后端都得到了簡化瓢颅,都基于統(tǒng)一的應用層協(xié)議HTTP來交互數(shù)據(jù),HTTP協(xié)議采用無狀態(tài)的短鏈接的通信方式弛说,通常情況下挽懦,一次請求就完成了一次數(shù)據(jù)交互,通常也對應一個業(yè)務邏輯木人,然后這次通信連接就斷開了信柿。采用這種方式是為了能夠同時服務更多的用戶,因為當前互聯(lián)網(wǎng)應用每天都會處理上億的用戶請求醒第,不可能每個用戶訪問一次后就一直保持住這個連接渔嚷。
當一個用戶在瀏覽器里輸入www.google.com這個URL時,將會發(fā)生如下操作:
首先稠曼,瀏覽器會請求DNS把這個域名解析成對應的IP地址形病;
然后,根據(jù)這個IP地址在互聯(lián)網(wǎng)上找到對應的服務器霞幅,建立Socket連接漠吻,向這個服務器發(fā)起一個HTTP Get請求,由這個服務器決定返回默認的數(shù)據(jù)資源給訪問的用戶司恳;
在服務器端實際上還有復雜的業(yè)務邏輯:服務器可能有多臺途乃,到底指定哪臺服務器處理請求,這需要一個負載均衡設備來平均分配所有用戶的請求扔傅;
還有請求的數(shù)據(jù)是存儲在分布式緩存里還是一個靜態(tài)文件中耍共,或是在數(shù)據(jù)庫里烫饼;
當數(shù)據(jù)返回瀏覽器時,瀏覽器解析數(shù)據(jù)發(fā)現(xiàn)還有一些靜態(tài)資源(如:css试读,js或者圖片)時又會發(fā)起另外的HTTP請求杠纵,而這些請求可能會在CDN上,那么CDN服務器又會處理這個用戶的請求钩骇;
以上具體流程淡诗,如圖所示:
以上具體流程,如圖所示
不管網(wǎng)絡架構如何變化伊履,但是始終有一些固定不變的原則需要遵守:
互聯(lián)網(wǎng)上所有資源都要用一個URL來表示韩容。URL就是統(tǒng)一資源定位符;
必須基于HTTP協(xié)議與服務端交互唐瀑;
數(shù)據(jù)展示必須在瀏覽器中進行群凶;
2 HTTP協(xié)議解析#
B/S網(wǎng)絡架構的核心是HTTP協(xié)議,最重要的就是要熟悉HTTP協(xié)議中的HTTP Header哄辣,HTTP Header控制著互聯(lián)網(wǎng)上成千上萬的用戶的數(shù)據(jù)傳輸请梢。最關鍵的是,它控制著用戶瀏覽器的渲染行為和服務器的執(zhí)行邏輯力穗。
常見的HTTP請求頭:
常見的HTTP請求頭
常見的HTTP響應頭:
常見的HTTP響應頭
常見的HTTP狀態(tài)碼:
常見的HTTP狀態(tài)碼
2.1 瀏覽器緩存機制##
當我們使用Ctrl+F5組合鍵刷新一個頁面時毅弧,首先是在瀏覽器端,會直接向目標URL發(fā)送請求当窗,而不會使用瀏覽器緩存的數(shù)據(jù)够坐;其次即使請求發(fā)送到服務端,也有可能訪問到的是緩存的數(shù)據(jù)崖面。所以在HTTP的請求頭中會增加一些請求頭元咙,它告訴服務端我們要獲取最新的數(shù)據(jù)而非緩存。最重要的是在請求Head中增加了兩個請求項Pragma:no-cache和Cache-Control:no-cache巫员。
Cache-Control/Pragma
這個HTTP Head字段用于指定所有緩存機制在整個請求/響應鏈中必須服從的指令庶香,如果知道該頁面是否為緩存,不僅可以控制瀏覽器简识,還可以控制和HTTP協(xié)議相關的緩存或代理服務器赶掖。
Cache-Control/Pragma字段的可選值:
Cache-Control/Pragma字段的可選值
Cache-Control請求字段被各個瀏覽器支持的較好,而且它的優(yōu)先級也比較高七扰,它和其他一些請求字段(如Expires)同時出現(xiàn)時奢赂,Cache-Control會覆蓋其他字段。
Pragma字段的作用和Cache-Control有點類似戳寸,它也是在HTTP頭中包含一個特殊的指令呈驶,使相關的服務器來遵守拷泽,最常用的就是Pragma:no-cache疫鹊,它和Cache-Control:no-cache的作用是一樣的袖瞻。
Expires 緩存過期時間
Expires通常的使用格式是Expires:Sat,25 Feb 2012 12:22:17 GMT,后面跟著一個日期和時間拆吆,超過這個值后聋迎,緩存的內容將失效,也就是瀏覽器在發(fā)出請求之前檢查這個頁面的這個字段枣耀,看該頁面是否已經(jīng)過期了霉晕,過期了將重新向服務器發(fā)起請求。
Last-Modified/Etag 最后修改時間
Last-Modified字段一般用于表示一個服務器上的字段的最后修改時間捞奕,資源可以是靜態(tài)(靜態(tài)內容自動加上Last-Modified)或者動態(tài)的內容(如Servlet提供了一個getLastModified方法用于檢查某個動態(tài)內容是否已經(jīng)更新)牺堰,通過這個最后修改時間可以判斷當前請求的資源是否是最新的。
一般服務器端在響應頭中返回一個Last-Modified字段颅围,告訴瀏覽器這個頁面的最后修改時間伟葫,如:Sat,25 Feb 2012 12:55:04 GMT,瀏覽器再次請求時在請求頭中增加一個If-Modified-Since:Sat,25 Feb 2012 12:55:04 GMT字段院促,詢問當前緩存的頁面是否是最新的筏养,如果是最新的就會返回304狀態(tài)碼,告訴瀏覽器是最新的常拓,服務器也不會傳輸新的數(shù)據(jù)渐溶。
與Last-Modified字段有類似功能的還有一個Etag字段,這個字段的作用是讓服務端給每個頁面分配一個唯一編號弄抬,然后通過這個編號來區(qū)分當前這個頁面是否是最新的茎辐。這種方式比使用Last-Modified更加靈活,但是在后端的Web服務器有多臺時比較難處理掂恕,因為每個Web服務器都要記住網(wǎng)站的所有資源編號荔茬,否則瀏覽器返回這個編號就沒有意義了。
3 WEB工作流程#
對于正常的上網(wǎng)過程竹海,系統(tǒng)其實是這樣做的:
瀏覽器本身是一個客戶端慕蔚,當你輸入URL的時候,首先瀏覽器會去請求DNS服務器斋配,通過DNS獲取相應的域名對應的IP孔飒,然后通過IP地址找到IP對應的服務器后,要求建立TCP連接艰争,等瀏覽器發(fā)送完HTTP Request(請求)包后坏瞄,服務器接收到請求包之后才開始處理請求包,服務器調用自身服務甩卓,返回HTTP Response(響應)包鸠匀;客戶端收到來自服務器的響應后開始渲染這個Response包里的主體(body),等收到全部的內容隨后斷開與該服務器之間的TCP連接逾柿。
Web請求的工作原理
Web請求的工作原理可以簡單地歸納為:
瀏覽器通過DNS域名解析到服務器IP缀棍;
客戶機通過TCP/IP協(xié)議建立到服務器的TCP連接宅此;
客戶端向服務器發(fā)送HTTP協(xié)議請求包,請求服務器里的資源文檔爬范;
服務器向客戶機發(fā)送HTTP協(xié)議應答包父腕,如果請求的資源包含有動態(tài)語言的內容,那么服務器會調用動態(tài)語言的解釋引擎負責處理“動態(tài)內容”青瀑,并將處理得到的數(shù)據(jù)返回給客戶端璧亮;
客戶機與服務器斷開。由客戶端解釋HTML文檔斥难,在客戶端屏幕上渲染圖形結果枝嘶;
一個簡單的HTTP事務就是這樣實現(xiàn)的,看起來很復雜哑诊,原理其實是挺簡單的躬络。需要注意的是客戶機與服務器之間的通信是非持久連接的,也就是當服務器發(fā)送了應答后就與客戶機斷開連接搭儒,等待下一次請求穷当。
4 DNS域名解析#
4.1 DNS域名解析過程##
當用戶在瀏覽器中輸入域名,如:www.google.com淹禾,并按下回車后馁菜,DNS解析過程大體如下:
DNS解析過程
瀏覽器緩存檢查(本機)
瀏覽器會首先搜索瀏覽器自身的DNS緩存(緩存時間比較短,大概只有1分鐘铃岔,且只能容納1000條緩存)汪疮,看自身的緩存中是否有www.google.com對應的條目,而且沒有過期毁习,如果有且沒有過期則解析到此結束智嚷。
瀏覽器緩存域名也是有限制的,不僅瀏覽器緩存大小有限制纺且,而且緩存的時間也有限制盏道,通常情況下為幾分鐘到幾小時不等,域名被緩存的時間限制可以通過TTL屬性來設置载碌。這個緩存時間太長和太短都不好猜嘱,如果緩存時間太長,一旦域名被解析到的IP有變化嫁艇,會導致被客戶端緩存的域名無法解析到變化后的IP地址朗伶,以致該域名不能正常解析,這段時間內有可能會有一部分用戶無法訪問網(wǎng)站步咪。如果時間設置太短论皆,會導致用戶每次訪問網(wǎng)站都要重新解析一次域名。
注:我們怎么查看Chrome自身的緩存?可以使用chrome://net-internals/#dns來進行查看
查看Chrome自身的DNS緩存
操作系統(tǒng)緩存檢查(本機)+hosts解析(本機)
如果瀏覽器自身的緩存里面沒有找到對應的條目点晴,其實操作系統(tǒng)也會有一個域名解析的過程感凤,那么Chrome會首先搜索操作系統(tǒng)自身的DNS緩存中是否有這個域名對應的DNS解析結果,如果找到且沒有過期則停止搜索解析到此結束觉鼻。
其次在Linux中可以通過/etc/hosts文件來設置俊扭,你可以將任何域名解析到任何能夠訪問的IP地址队橙。如果你在這里指定了一個域名對應的IP地址坠陈,那么瀏覽器會首先使用這個IP地址。當解析到這個配置文件中的某個域名時捐康,操作系統(tǒng)會在緩存中緩存這個解析結果仇矾,緩存的時間同樣是受這個域名的失效時間和緩存的空間大小控制的。
本地區(qū)域名服務器解析(LDNS)
如果在hosts文件中也沒有找到對應的條目解总,瀏覽器就會發(fā)起一個DNS的系統(tǒng)調用贮匕,就會向本地配置的首選DNS服務器(LDNS一般是電信運營商提供的,也可以使用像Google提供的DNS服務器)發(fā)起域名解析請求(通過的是UDP協(xié)議向DNS的53端口發(fā)起請求花枫,這個請求是遞歸的請求刻盐,也就是運營商的DNS服務器必須得提供給我們該域名的IP地址)。
在我們的網(wǎng)絡配置中都會有“DNS服務器地址”這一項劳翰,這個地址就用于解決前面所說的如果兩個過程無法解析時要怎么辦敦锌,操作系統(tǒng)會把這個域名發(fā)送給這里設置的LDNS,也就是本地區(qū)的域名服務器佳簸。這個DNS通常都提供給你本地互聯(lián)網(wǎng)接入的一個DNS解析服務乙墙,例如你是在學校接入互聯(lián)網(wǎng),那么你的DNS服務器肯定在你的學校生均,如果你是在一個小區(qū)接入互聯(lián)網(wǎng)的听想,那這個DNS就是提供給你接入互聯(lián)網(wǎng)的應用提供商,即電信或者聯(lián)通马胧,也就是通常所說的SPA汉买,那么這個DNS通常也會在你所在城市的某個角落,通常不會很遠佩脊。這個專門的域名解析服務器性能都會很好录别,它們一般都會緩存域名解析結果,當然緩存時間是受域名的失效時間控制的邻吞,一般緩存空間不是影響域名失效的主要因素组题。大約80%的域名解析都到這里就已經(jīng)完成了,所以LDNS主要承擔了域名的解析工作抱冷。
運營商的DNS服務器首先查找自身的緩存崔列,找到對應的條目淆衷,且沒有過期,則解析成功顿痪。
運營商的DNS服務器
根域名服務器解析(Root Server)
如果LDNS沒有找到對應的條目蘑斧,則由運營商的DNS代我們的瀏覽器發(fā)起迭代DNS解析請求。它首先是會找根域的DNS的IP地址(這個DNS服務器都內置13臺根域的DNS的IP地址)边翼,找到根域的DNS地址鱼响,就會向其發(fā)起請求(請問www.google.com這個域名的IP地址是多少啊组底?)丈积。
根域名服務器返回給本地域名服務器一個所查詢域的主域名服務器(gTLD Server)地址,gTLD是國際頂級域名服務器债鸡,如.com江滨、.cn、.org等厌均,全球只有13臺左右唬滑。
根域發(fā)現(xiàn)這是一個頂級域com域的一個域名,于是就告訴運營商的DNS我不知道這個域名的IP地址棺弊,但是我知道com域的IP地址晶密,你去找它去。
本地域名服務器(Local DNS Server)再向上一步返回的gTLD服務器發(fā)送請求模她。
于是運營商的DNS就得到了com域的IP地址稻艰,又向com域的IP地址發(fā)起了請求(請問www.google.com這個域名的IP地址是多少?),com域這臺服務器告訴運營商的DNS我不知道www.google.com這個域名的IP地址缝驳,但是我知道google.com這個域的DNS地址连锯,你去找它去。
接受請求的gTLD服務器查找并返回此域名對應的Name Server域名服務器的地址用狱,這個Name Server通常就是你注冊的域名服務器运怖,例如你在某個域名服務提供商申請的域名,那么這個域名解析任務就由這個域名提供商的服務器來完成夏伊。
于是運營商的DNS又向google.com這個域名的DNS地址(這個一般就是由域名注冊商提供的摇展,像萬網(wǎng),新網(wǎng)等)發(fā)起請求(請問www.google.com這個域名的IP地址是多少溺忧?)咏连,這個時候google.com域的DNS服務器一查,果真在我這里鲁森,于是就把找到的結果發(fā)送給運營商的DNS服務器祟滴,這個時候運營商的DNS服務器就拿到了www.google.com這個域名對應的IP地址。
Name Server域名服務器會查詢存儲的域名和IP的映射關系表歌溉,正常情況下都根據(jù)域名得到目標IP記錄垄懂,連同一個TTL值返回給DNS Server域名服務器骑晶。
返回該域名對應的IP和TTL值,Local DNS Server會緩存這個域名和IP的對應關系草慧,緩存的時間由TTL值控制桶蛔。
把解析的結果返回給用戶,用戶根據(jù)TTL值緩存在本地系統(tǒng)緩存中漫谷,域名解析過程結束仔雷。
通過上面的步驟,我們最后獲取的是IP地址舔示,也就是瀏覽器最后發(fā)起請求的時候是基于IP來和服務器做信息交互的碟婆。在實際的DNS解析過程中,可能還不止這10個步驟斩郎,如Name Server也可能有多級脑融,或者有一個GTM來負載均衡控制喻频,這都有可能會影響域名解析的過程缩宜。根據(jù)以上解析流程,DNS解析整個過程甥温,分為:遞歸查詢過程和迭代查詢過程锻煌。如圖所示:
DNS解析整個過程
所謂 遞歸查詢過程 就是 “查詢的遞交者” 更替, 而 迭代查詢過程 則是 “查詢的遞交者”不變。
舉個例子來說姻蚓,你想知道某個一起上法律課的女孩的電話宋梧,并且你偷偷拍了她的照片,回到寢室告訴一個很仗義的哥們兒狰挡,這個哥們兒二話沒說捂龄,拍著胸脯告訴你,甭急加叁,我替你查(此處完成了一次遞歸查詢倦沧,即,問詢者的角色更替)它匕。然后他拿著照片問了學院大四學長展融,學長告訴他,這姑娘是xx系的豫柬;然后這哥們兒馬不停蹄又問了xx系的辦公室主任助理同學告希,助理同學說是xx系yy班的,然后很仗義的哥們兒去xx系yy班的班長那里取到了該女孩兒電話烧给。(此處完成若干次迭代查詢燕偶,即,問詢者角色不變础嫡,但反復更替問詢對象)最后指么,他把號碼交到了你手里。完成整個查詢過程。
4.2 跟蹤域名解析過程##
在Linux系統(tǒng)中還可以使用dig命名來查詢DNS的解析過程涧尿,如下所示:dig +cmd +trace www.google.com
使用dig命名來查詢DNS的解析過程
上面清楚地顯示了整個域名是如何發(fā)起和解析的系奉,從根域名(.)到gTLD Server(.com.)再到Name Server (google.com.)的整個過程都顯示出來了。還可以看出DNS的服務器有多個備份姑廉,可以從任何一臺查詢到解析結果缺亮。
4.3 清除緩存的域名##
我們知道DNS域名解析后會緩存解析結果,其中主要在兩個地方緩存結果桥言,一個是Local DNS Server萌踱,另外一個是用戶的本地機器。這兩個緩存都是TTL值和本機緩存大小控制的号阿,但是最大緩存時間是TTL值并鸵,基本上Local DNS Server的緩存時間就是TTL控制的,很難人工介入扔涧,但是我們的本機緩存可以通過如下方式清除园担。
在Linux下可以通過/etc/init.d/nscd restart來清除DNS緩存。如下:
在Linux下清除DNS緩存
JVM緩存DNS解析結果:
在Java應用中JVM也會緩存DNS的解析結果枯夜,這個緩存是在InetAddress類中完成的弯汰,而且這個緩存時間還比較特殊,它有兩種緩存策略:一種是正確解析結果緩存湖雹,另一種是失敗的解析結果緩存咏闪。這兩個緩存時間由兩個配置項控制,配置項是在%JAVA_ HOME%\lib\security\java.security文件中配置的摔吏。兩個配置項分別是networkaddress.cache.ttl 和networkaddress.cache.negative.ttl鸽嫂,它們的默認值分別是-1(永不失效)和10(緩存10秒)。
要修改這兩個值同樣有幾種方式征讲,分別是:直接修改java.security文件中的默認值据某、在Java的啟動參數(shù)中增加-Dsun.net.inetaddr.ttl=xxx來修改默認值、通過InetAddress類動態(tài)修改稳诚。
在這里還要特別強調一下哗脖,如果我們需要用InetAddress類解析域名時,一定要是單例模式扳还,不然會有嚴重的性能問題才避,如果每次都創(chuàng)建InetAddress實例,每次都要進行一次完整的域名解析氨距,非常耗時桑逝,這點要特別注意。
4.4 幾種域名解析方式##
A記錄俏让,A代表的是Address楞遏,用來指定域名對應的IP地址
如將item.taobao.com指定到115.238.23.241茬暇,將switch.taobao.com指定到121.14.24.241。A記錄可以將多個域名解析到一個IP地址寡喝,但是不能將一個域名解析到多個IP地址糙俗。
MX記錄,表示的是Mail Exchange预鬓,就是可以將某個域名下的郵件服務器指向自己的Mail Server
如taobao.com域名的A記錄IP地址是115.238.25.245巧骚,如果MX記錄設置為115.238.25.246,是xxx@taobao.com的郵件路由格二,DNS會將郵件發(fā)送到115.238.25.246所在的服務器劈彪,而正常通過Web請求的話仍然解析到A記錄的IP地址。
CNAME記錄顶猜,全稱是Canonical Name(別名解析)沧奴,所謂的別名解析就是可以為一個域名設置一個或者多個別名
如將taobao.com解析到xulingbo.net,將srcfan.com也解析到xulingbo.net长窄,其中xulingbo.net分別是taobao.com和srcfan.com的別名滔吠。前面的跟蹤域名解析中的“www.taobao.com. 1542 IN CNAMEwww.gslb.taobao.com”就是CNAME解析。
NS記錄抄淑,為某個域名指定DNS解析服務器屠凶,也就是這個域名有指定的IP地址的DNS服務器去解析
前面的“google.com. 172800 IN NS? ns4.google.com.”就是NS解析驰后。
TXT記錄肆资,為某個主機名或域名設置說明
如可以為google.com設置TXT記錄為“谷歌|中國”這樣的說明。
4.5 網(wǎng)絡抓包分析##
Linux虛擬機測試灶芝,使用命令 wget www.linux178.com 來請求郑原,發(fā)現(xiàn)直接使用chrome瀏覽器請求時,干擾請求比較多夜涕,所以就使用wget命令來請求犯犁,不過使用wget命令只能把index.html請求回來,并不會對index.html中包含的靜態(tài)資源(js女器、css等文件)進行請求酸役。
抓包截圖如下:
抓包截圖
1號包,這個是那臺虛擬機在廣播驾胆,要獲取192.168.100.254(也就是網(wǎng)關)的MAC地址涣澡,因為局域網(wǎng)的通信靠的是MAC地址,它為什么需要跟網(wǎng)關進行通信是因為我們的DNS服務器IP是外圍IP丧诺,要出去必須要依靠網(wǎng)關幫我們出去才行入桂。
2號包,這個是網(wǎng)關收到了虛擬機的廣播之后驳阎,回應給虛擬機的回應抗愁,告訴虛擬機自己的MAC地址馁蒂,于是客戶端找到了路由出口。
3號包蜘腌,這個包是wget命令向系統(tǒng)配置的DNS服務器提出域名解析請求(準確的說應該是wget發(fā)起了一個DNS解析的系統(tǒng)調用)沫屡,請求的域名www.linux178.com,期望得到的是IP6的地址(AAAA代表的是IPv6地址)撮珠。
4號包谁鳍,這個DNS服務器給系統(tǒng)的響應,很顯然目前使用IPv6的還是極少數(shù)劫瞳,所以得不到AAAA記錄的倘潜。
5&6號包,這個還是請求解析IPv6地址志于,但是www.linux178.com.leo.com這個主機名是不存在的涮因,所以得到結果就是no such name。
7號包伺绽,這個才是請求的域名對應的IPv4地址(A記錄)养泡。
8號包,DNS服務器不管是從緩存里面奈应,還是進行迭代查詢最終得到了域名的IP地址澜掩,響應給了系統(tǒng),系統(tǒng)再給了wget命令杖挣,wget于是得到了www.linux178.com的IP地址肩榕,這里也可以看出客戶端和本地的DNS服務器是遞歸的查詢(也就是服務器必須給客戶端一個結果)這就可以開始下一步了,進行TCP的三次握手惩妇。
5 發(fā)起TCP的3次握手#
拿到域名對應的IP地址之后株汉,User-Agent(一般是指瀏覽器)會以一個隨機端口(1024 < 端口 < 65535)向服務器的WEB程序(常用的有httpd,nginx等)80端口發(fā)起TCP的連接請求。這個連接請求(原始的http請求經(jīng)過TCP/IP4層模型的層層封包)到達服務器端后(這中間通過各種路由設備歌殃,局域網(wǎng)內除外)乔妈,進入到網(wǎng)卡,然后是進入到內核的TCP/IP協(xié)議棧(用于識別該連接請求氓皱,解封包路召,一層一層的剝開),還有可能要經(jīng)過Netfilter防火墻(屬于內核的模塊)的過濾波材,最終到達WEB程序股淡,最終建立了TCP/IP的連接。
如下圖所示:
03174517_saG0.png
Client首先發(fā)送一個連接試探各聘,ACK=0 表示確認號無效揣非,SYN = 1 表示這是一個連接請求或連接接受報文,同時表示這個數(shù)據(jù)報不能攜帶數(shù)據(jù)躲因,seq = x 表示Client自己的初始序號(seq = 0 就代表這是第0號包)早敬,這時候Client進入syn_sent狀態(tài)忌傻,表示客戶端等待服務器的回復。
Server監(jiān)聽到連接請求報文后搞监,如同意建立連接水孩,則向Client發(fā)送確認。TCP報文首部中的SYN 和 ACK都置1 琐驴,ack = x + 1表示期望收到對方下一個報文段的第一個數(shù)據(jù)字節(jié)序號是x+1俘种,同時表明x為止的所有數(shù)據(jù)都已正確收到(ack=1其實是ack=0+1,也就是期望客戶端的第1個包),seq = y 表示Server自己的初始序號(seq=0就代表這是服務器這邊發(fā)出的第0號包)绝淡。這時服務器進入syn_rcvd宙刘,表示服務器已經(jīng)收到Client的連接請求,等待client的確認牢酵。
Client收到確認后還需再次發(fā)送確認悬包,同時攜帶要發(fā)送給Server的數(shù)據(jù)。ACK 置1 表示確認號ack= y + 1 有效(代表期望收到服務器的第1個包)馍乙,Client自己的序號seq= x + 1(表示這就是我的第1個包布近,相對于第0個包來說的),一旦收到Client的確認之后丝格,這個TCP連接就進入Established狀態(tài)撑瞧,就可以發(fā)起http請求了。
看抓包截圖:
抓包截圖
TCP 為什么需要3次握手显蝌?
舉個例子:假設一個老外在故宮里面迷路了预伺,看到了小明,于是就有下面的對話:
老外: Excuse me琅束,Can you Speak English?
小明: yes 扭屁。
老外: OK,I want ...
在問路之前,老外先問小明是否會說英語涩禀,小明回答是的,這時老外才開始問路然眼。
2個計算機通信是靠協(xié)議(目前流行的TCP/IP協(xié)議)來實現(xiàn),如果2個計算機使用的協(xié)議不一樣艾船,那是不能進行通信的,所以這個3次握手就相當于試探一下對方是否遵循TCP/IP協(xié)議高每,協(xié)商完成后就可以進行通信了屿岂,當然這樣理解不是那么準確。
為什么HTTP協(xié)議要基于TCP來實現(xiàn)鲸匿?
目前在Internet中所有的傳輸都是通過TCP/IP進行的爷怀,HTTP協(xié)議作為TCP/IP模型中應用層的協(xié)議也不例外,TCP是一個端到端的可靠的面向連接的協(xié)議带欢,所以HTTP基于傳輸層TCP協(xié)議不用擔心數(shù)據(jù)的傳輸?shù)母鞣N問題运授。
6 建立TCP連接后發(fā)起http請求#
經(jīng)過TCP3次握手之后烤惊,瀏覽器發(fā)起了http的請求(看第?包),使用的http的方法 GET 方法吁朦,請求的URL是 / ,協(xié)議是HTTP/1.0:
03175340_4j8z.png
下面是第12號包的詳細內容:
03175429_kHoP.png
以上的報文是HTTP請求報文柒室。那么HTTP請求報文和響應報文會是什么格式呢?
起始行:如 GET / HTTP/1.0 (請求的方法? 請求的URL 請求所使用的協(xié)議)
頭部信息:User-Agent? Host等成對出現(xiàn)的值
主體
不管是請求報文還是響應報文都會遵循以上的格式逗宜。那么起始行中的請求方法有哪些種呢雄右?
GET: 完整請求一個資源 (常用)
HEAD: 僅請求響應首部
POST: 提交表單? (常用)
PUT: 上傳
DELETE: 刪除
OPTIONS: 返回請求的資源所支持的方法的方法
TRACE: 追求一個資源請求中間所經(jīng)過的代理
那什么是URL、URI纺讲、URN擂仍?
URI? Uniform Resource Identifier 統(tǒng)一資源標識符,如:scheme://[username:password@]HOST:port/path/to/source
URL? Uniform Resource Locator 統(tǒng)一資源定位符熬甚,如:http://www.magedu.com/downloads/nginx-1.5.tar.gz
URN? Uniform Resource Name 統(tǒng)一資源名稱
URL和URN都屬于URI防楷,為了方便就把URL和URI暫時都通指一個東西。
請求的協(xié)議有哪些種则涯?有以下幾種:
http/0.9: stateless
http/1.0: MIME, keep-alive (保持連接), 緩存
http/1.1: 更多的請求方法复局,更精細的緩存控制,持久連接(persistent connection) 比較常用
下面是Chrome發(fā)起的http請求報文頭部信息:
03181252_cIE1.png
Accept 就是告訴服務器端粟判,接受那些MIME類型
Accept-Encoding 這個看起來是接受那些壓縮方式的文件
Accept-Lanague 告訴服務器能夠發(fā)送哪些語言
Connection 告訴服務器支持keep-alive特性亿昏,TCP連接在發(fā)送后將仍然保持打開狀態(tài),于是档礁,瀏覽器可以繼續(xù)通過相同的TCP連接發(fā)送請求角钩。保持連接節(jié)省了為每個請求建立新連接所需的時間,還節(jié)約了網(wǎng)絡帶寬呻澜。
Cookie 每次請求時都會攜帶上Cookie以方便服務器端識別是否是同一個客戶端
Host 用來標識請求服務器上的那個虛擬主機递礼,比如Nginx里面可以定義很多個虛擬主機,那這里就是用來標識要訪問那個虛擬主機羹幸。
User-Agent 用戶代理脊髓,一般情況是瀏覽器,也有其他類型栅受,如:wget curl 搜索引擎的蜘蛛等
條件請求頭部:If-Modified-Since是瀏覽器向服務器端詢問某個資源文件如果自從什么時間修改過将硝,那么重新發(fā)給我,這樣就保證服務器端資源文件更新時屏镊,瀏覽器再次去請求依疼,而不是使用緩存中的文件。
安全請求頭部:Authorization: 客戶端提供給服務器的認證信息而芥;
什么是MIME律罢?
MIME(Multipurpose Internet Mail Extesions
多用途互聯(lián)網(wǎng)郵件擴展)是一個互聯(lián)網(wǎng)標準,它擴展了電子郵件標準棍丐,使其能夠支持非ASCII字符误辑、二進制格式附件等多種格式的郵件消息沧踏,這個標準被定義在RFC
2045、RFC 2046稀余、RFC 2047悦冀、RFC 2048、RFC 2049等RFC中睛琳。 由RFC 822轉變而來的RFC
2822盒蟆,規(guī)定電子郵件標準并不允許在郵件消息中使用7位ASCII字符集以外的字符。正因如此师骗,一些非英語字符消息和二進制文件历等,圖像,聲音等非文字消息都不能在電子郵件中傳輸辟癌。
MIME規(guī)定了用于表示各種各樣的數(shù)據(jù)類型的符號化方法寒屯。此外,在萬維網(wǎng)中使用的HTTP協(xié)議中也使用了MIME的框架黍少,標準被擴展為互聯(lián)網(wǎng)媒體類型寡夹。
MIME 遵循以下格式:major/minor 主類型/次類型例如:
image/jpg
image/gif
text/html
video/quicktime
appliation/x-httpd-php