Telnet 訪問網(wǎng)站方式
- 運(yùn)行 CMD
- telnet 網(wǎng)址 端口號。如:telnet www.example.com 80
- 輸入請求行。如:GET /index.html HTTP/1.1
完成上面三步回車后即可看到服務(wù)器返回的原始數(shù)據(jù)归敬。
Note
由于 Window 自帶的 Telnet 在輸入內(nèi)容是看不到輸入內(nèi)容的贤壁,可以使用 putty 并選用 raw connection
的方式進(jìn)行連接苔货。具體的 PUTTY 訪問 HTTP 連接的方式如下:
- 下載 PUTTY妈候,并進(jìn)行配置敢靡,如下圖:
- 輸入 HTTP 請求頭信息,主要是包含請求行 + Host 主機(jī)名(HTTP 唯一必填的頭字段)苦银,輸入完成后啸胧,需要輸入兩個(gè)回車,第一個(gè)回車表示當(dāng)前請求字段輸入完畢幔虏,第二個(gè)回車表示所有請求頭字段輸入完畢后留出的空行纺念。如下圖:
1. HTTP 協(xié)議是什么
HTTP 是一個(gè)計(jì)算機(jī)世界里專門用來在兩點(diǎn)之間傳輸文字、圖片想括、音頻陷谱、視頻等超文本數(shù)據(jù)的約定和規(guī)范。
協(xié)議的意思
- 協(xié)議必須要有兩個(gè)或以上的參與者瑟蜈,也就是“協(xié)”
- 協(xié)議是對參與者的一種行為約束和規(guī)范烟逊,也就是“議”
2. HTTP 歷史
2.1 第一個(gè)階段:HTTP/0.9(20 世紀(jì) 90 年代初)
- 采用純文本格式
- 由于最初設(shè)想里的文檔都是只讀的,所以铺根,只允許通過
GET
操作拉取 HTML 數(shù)據(jù) - 響應(yīng)請求后立即關(guān)閉連接(短連接)
2.2 第二個(gè)階段:HTTP/1.0(1996 年正式發(fā)布)
在 0.9 的基礎(chǔ)上宪躯,做了下面改動:
- 增加了 HEAD、POST等新方法
- 增加了響應(yīng)狀態(tài)碼夷都,標(biāo)記可能的錯(cuò)誤原因
- 引入了協(xié)議版本號概念
- 引入了 HTTP Header 概念眷唉,讓 Http 處理請求和響應(yīng)更加容易
- 傳輸協(xié)議不再僅限于文本
只是一個(gè)“參考文檔”。
2.3 第三個(gè)階段:HTTP/1.1(1999 發(fā)布)
在 1.0 的基礎(chǔ)上進(jìn)行了小幅的修正囤官,和 1.0 的一個(gè)最主要區(qū)別是:1.1 是一個(gè)“正式的標(biāo)準(zhǔn)”冬阳。
- 增加了 PUT、DELETE 等新的方法
- 增加了緩存管理和控制
- 明確了連接管理党饮,允許持久連接
- 允許響應(yīng)數(shù)據(jù)分塊(chunked)肝陪,利用數(shù)據(jù)大文件
- 強(qiáng)制要求 Host 頭,讓互聯(lián)網(wǎng)主機(jī)托管成為可能
2.4 第四個(gè)階段:HTTP/2.0(2015 年正式發(fā)布)
基于 GOOGLE 開發(fā)的 SPY 協(xié)議而來刑顺。主要特點(diǎn)為:
- 二進(jìn)制協(xié)議氯窍,不再是純文本
- 可發(fā)起多個(gè)請求饲常,廢棄了 1.1 里的管道
- 使用專用算法壓縮頭部,減少數(shù)據(jù)傳輸量
- 允許服務(wù)器主動向客戶端推送數(shù)據(jù)
- 增強(qiáng)了安全性狼讨,要求加密通信
2.4.1 二進(jìn)制協(xié)議和純文本協(xié)議的區(qū)別
疑問
無論是文本協(xié)議還是二進(jìn)制協(xié)議贝淤,數(shù)據(jù)從 A 電腦傳到 B 電腦的過程,傳輸?shù)臄?shù)據(jù)都是二進(jìn)制的 0 和 1 政供。 為什么還有純文本協(xié)議和二進(jìn)制協(xié)議呢播聪?
純文本協(xié)議:使用 ASCII 碼進(jìn)行編碼的協(xié)議。好處:所見即所得布隔,用最簡單的工具就可以開發(fā)調(diào)試离陶,非常方便。
二進(jìn)制協(xié)議:直接傳輸 01 字節(jié)數(shù)據(jù)衅檀,不需要進(jìn)行編碼招刨,但一般都有對定義數(shù)據(jù)的結(jié)構(gòu),比如:圖片哀军、視頻沉眶、音頻等二進(jìn)制協(xié)議,在數(shù)據(jù)頭部都有專門的協(xié)議標(biāo)識杉适,用來告訴接收方沦寂,我這是什么數(shù)據(jù),需要用什么才能進(jìn)行解釋淘衙。如果沒有用指定的工具查看的話,看到的將會是一堆亂碼腻暮。
二進(jìn)制協(xié)議相比純文本的好處:
減少數(shù)據(jù)包的大小彤守。比如:一個(gè)字符使用 ASCII 碼(只支持英文字母和符號)占一個(gè)字節(jié),如果要傳遞一個(gè) 655110 這個(gè)數(shù)據(jù)哭靖,需要使用 6 個(gè)字節(jié)具垫,而如果直接使用二進(jìn)制數(shù)據(jù),只需要 2 個(gè)字節(jié)(16 位)就可以表示所有 Int 類型的數(shù)據(jù)试幽。顯然筝蚕,二進(jìn)制比純文本更加節(jié)省空間。
2.5 第五個(gè)階段:HTTP/3.0(2018 年進(jìn)入標(biāo)準(zhǔn)化制定階段)
基于 GOOGLE 的 QUIC 協(xié)議而來铺坞。
2.5.1 什么是 QUIC起宽?
QUIC(Quick UDP Internet Connections)基于UDP的傳輸層協(xié)議,提供像TCP一樣的可靠性济榨。
2.5.2 什么是隊(duì)頭阻塞問題坯沪?
HTTP 收發(fā)數(shù)據(jù)是一個(gè)先進(jìn)先出的“串行”隊(duì)列,如果隊(duì)首的請求由于處理的太慢擒滑,后面的數(shù)據(jù)就不得不等待腐晾,導(dǎo)致其它的請求承擔(dān)了不應(yīng)有的時(shí)間成本叉弦。
協(xié)議之外的解決方法
- 并發(fā)連接。一般是通過創(chuàng)建一個(gè)連接池藻糖,對連接進(jìn)行復(fù)用的方式進(jìn)行并發(fā)的請求淹冰,也就是只要連接池里的連接沒有被使用完,每個(gè)連接都是并發(fā)執(zhí)行的巨柒,不會出現(xiàn)由于串行導(dǎo)致的隊(duì)頭阻塞問題樱拴。
- 域名分片。也就是多個(gè)域名指向同一個(gè)服務(wù)器潘拱,突破 HTTP 和瀏覽器對并發(fā)數(shù)量的限制疹鳄。
協(xié)議本身的解決方法
- HTTP 2.0 將 Header 和 Body 的消息“打散”為數(shù)據(jù)小片的二進(jìn)制“幀”,用“HEADERS”幀放頭部數(shù)據(jù)芦岂,“DATA”幀存放實(shí)體數(shù)據(jù)瘪弓。同時(shí),在應(yīng)用層引入了“流”的概念禽最,二進(jìn)制“幀”可以在“流”上雙向傳輸腺怯。同一個(gè)消息往返的幀會分配一個(gè)唯一的流 ID。多個(gè)消息往返會分配多個(gè)流 ID川无,也就是在同一連接中構(gòu)建了多個(gè)虛擬的“數(shù)據(jù)流”呛占,在同一個(gè)連接中同時(shí)亂序發(fā)送數(shù)據(jù)。這里要注意的是:同一個(gè)流 ID 的數(shù)據(jù)傳遞是有序的懦趋,只是不同流 ID 的數(shù)據(jù)是并行發(fā)送的晾虑。但由于傳輸層使用的是 TCP ,所以數(shù)據(jù)在經(jīng)過傳輸層的時(shí)候仅叫,還是串行進(jìn)行發(fā)送的帜篇,所以,瓶頸就從應(yīng)用層轉(zhuǎn)移到了傳輸層诫咱。下圖是 HTTP 2 在應(yīng)用層并發(fā)數(shù)據(jù)的情況笙隙。
- HTTP 3.0 讓 HTTP 運(yùn)行在了 QUIC 上,而不是 TCP 上坎缭。完美解決了“隊(duì)頭阻塞”的問題竟痰。QUIC 在 UDP 上把 TCP 的那一套連接管理、擁塞窗口掏呼、流量控制等直接在 QUIC 上進(jìn)行了重新更加優(yōu)化的實(shí)現(xiàn)坏快。
3. OSI 和 TCP/IP 協(xié)議棧
3.1 OSI 和 TCP/IP 的關(guān)系
TCP/IP 網(wǎng)絡(luò)分層模型發(fā)明于 1970 年,在當(dāng)年還有很多其它的網(wǎng)絡(luò)分層模型憎夷,但由于 TCP/IP 已被廣泛應(yīng)用假消,且其擴(kuò)展性也較強(qiáng),于是 ISO(國際標(biāo)準(zhǔn)化組織)基于 TCP/IP 制定了統(tǒng)一的網(wǎng)絡(luò)分層模型岭接。
OSI 全稱是“開放式系統(tǒng)互聯(lián)通信參考模型”富拗,由于在 OSI 推出之前臼予,TCP/IP 已經(jīng)被廣泛應(yīng)用,ISO 標(biāo)準(zhǔn)化組織也很清楚啃沪,將其推倒重來也是不太現(xiàn)實(shí)的粘拾,所以,OSI 在發(fā)布的時(shí)候创千,就表明自己只是一個(gè)參考模型缰雇,沒有強(qiáng)制約束力。
3.2 OSI 和 TCP/IP 的網(wǎng)絡(luò)層次的對應(yīng)關(guān)系
從上圖中可以看出追驴,網(wǎng)絡(luò)層和傳輸層兩都一致械哟,而在網(wǎng)絡(luò)層之下,TCP/IP 協(xié)議棧只定義了鏈路層(MAC)殿雪,而 OSI 模型更加全面暇咆,將物理層也包含了進(jìn)來。
同樣的丙曙,在傳輸層之上爸业,TCP 將其全部劃分為應(yīng)用層,而在 OSI 模型上將其細(xì)分為會話層亏镰、表示層和應(yīng)用層扯旷。其中,會話層主要是用來維護(hù)網(wǎng)絡(luò)中的狀態(tài)索抓,即保持會話和同步钧忽;表示層主要是把數(shù)據(jù)轉(zhuǎn)換為合適的,可以理解的語法和語義逼肯;應(yīng)用層就是面向具體的應(yīng)用傳輸數(shù)據(jù)惰瓜。
但由于 OSI 將傳輸層之上的分層過細(xì),而 TCP/IP 實(shí)際應(yīng)用時(shí)的會話管理汉矿、編碼轉(zhuǎn)換和壓縮等和具體應(yīng)用經(jīng)常聯(lián)系得很緊密,很難分開备禀,結(jié)果就是 OSI 上三層很難在具體應(yīng)用的過程中實(shí)施洲拇。
3.3 一次 HTTP 數(shù)據(jù)請求對應(yīng) TCP/IP 協(xié)議棧的處理
從上圖可以看出,HTTP 請求所傳輸?shù)臄?shù)據(jù)在應(yīng)用層被打上了一個(gè) HTTP Header
標(biāo)簽后傳遞到傳輸層曲尸;傳輸層收到后赋续,在應(yīng)用層 Message 的基礎(chǔ)上,打上了一個(gè) TCP Header
標(biāo)簽后又傳遞給了網(wǎng)際層另患;網(wǎng)絡(luò)層收到傳輸層發(fā)過來的 Segment 的基礎(chǔ)上纽乱,以打上了一個(gè) IP Header
標(biāo)簽后又傳遞給了數(shù)據(jù)鏈路層;數(shù)據(jù)鏈路層收到網(wǎng)際層發(fā)過來的 Package 后昆箕,在其基礎(chǔ)上打上了 Ethernet Header
標(biāo)簽后鸦列,將封裝好的 frame 數(shù)據(jù)通過物理線纜傳遞出去租冠。
這個(gè)時(shí)候,會有一個(gè)設(shè)備收到這個(gè)廣播(數(shù)據(jù)鏈路層都是通過廣播來通信的)薯嗤,這里假設(shè)路由器收到了這個(gè) frame 數(shù)據(jù)包顽爹。它會脫掉數(shù)據(jù)包中的 frame 頭部,并解析獲取到目的 MAC 地址骆姐,如果目的 MAC
地址不是自己镜粤,就直接丟棄;如果是自己的玻褪,就會把報(bào)文送到網(wǎng)絡(luò)層進(jìn)行解析肉渴,此時(shí),路由器脫掉并解析數(shù)據(jù)包的 IP 頭部信息带射,并檢查目的 IP 地址是否是自己同规,如果不是,就查詢本地路由表庸诱,找到目標(biāo) IP 地址對應(yīng)自己的出口端口捻浦,再給報(bào)文封裝上目的 IP 和源 IP 地址,并通過路由表中的下一跳 IP 地址查 ARP 表桥爽,獲取到下一跳 IP 地址對應(yīng)的 MAC 地址朱灿,并將報(bào)文打上 Frame 頭,其中钠四,目的 MAC 地址為下一跳 IP 地址對應(yīng)的 MAC 地址盗扒,源地址為當(dāng)前路由器出口對應(yīng)的 MAC 地址。
Frame 數(shù)據(jù)由下一跳 IP 地址所對應(yīng)的設(shè)備收到后缀去,此時(shí)假設(shè)是目的主機(jī)侣灶。目的主機(jī)收到 Frame 數(shù)據(jù)后,會脫掉并解析幀頭部缕碎,發(fā)現(xiàn)目的 MAC 地址是自己褥影,于是,將 IP 報(bào)文將由網(wǎng)絡(luò)層來處理咏雌。網(wǎng)絡(luò)層解析到目的 IP 地址后凡怎,發(fā)現(xiàn)目標(biāo) IP 地址是自己,則將 TCP 的 Segment 段數(shù)據(jù)交由傳輸層處理赊抖。傳輸層同樣的脫掉 TCP 頭部數(shù)據(jù)统倒,并將數(shù)據(jù)交由應(yīng)用層處理。應(yīng)用層脫掉并解析 HTTP 報(bào)頭氛雪,打到對應(yīng)的端口號房匆,并通過端口號將數(shù)據(jù)轉(zhuǎn)發(fā)給對應(yīng)的應(yīng)用進(jìn)行處理。
到此,一個(gè)完整的 HTTP 請求過程就完成了浴鸿。主要就是在當(dāng)前設(shè)備上依次封裝對數(shù)據(jù)包進(jìn)行封裝(也就是打上對應(yīng)層的標(biāo)簽)井氢,并通過重復(fù)解析和再封裝數(shù)據(jù)鏈路層和網(wǎng)際層的數(shù)據(jù)頭部信息(也就是不斷的在數(shù)據(jù)鏈路層和網(wǎng)絡(luò)層之間進(jìn)行數(shù)據(jù)的傳輸)。直到數(shù)據(jù)包到了目標(biāo) IP 地址所匹配的主機(jī)后赚楚,再將帶有 TCP 頭的報(bào)文交由傳輸層處理后毙沾,再將帶有 HTTP 頭的報(bào)文將由應(yīng)用層處理,最后通過目標(biāo)端口將真實(shí)數(shù)據(jù)傳遞給目標(biāo)應(yīng)用處理宠页。
4. HTTP 請求-響應(yīng)
4.1 一次 HTTP 請求響應(yīng)過程
整個(gè)過程可以根據(jù)圖上的序號來進(jìn)行說明:
1:客戶端使用端口號 5053 與服務(wù)器發(fā)送 SYN 請求左胞,試圖與服務(wù)器建立 TCP 連接
2:服務(wù)器發(fā)送 SYN + ACK
包,對客戶端發(fā)送過來的 SYN 請求進(jìn)行響應(yīng)举户。其中烤宙,SYN 中 Req 值為服務(wù)器生成的 0,而 ACK 值是對客戶端 SYN 的響應(yīng)俭嘁,其值為客戶端 SYN 值 + 1
躺枕,表示“我已經(jīng)收到你的請求了,并且已經(jīng)同意和你(客戶端)建立連接供填,你愿意和我建立連接么拐云?”
3:客戶端收到服務(wù)器的 SYN + ACK
包后,發(fā)送 ACK 確認(rèn)包給服務(wù)器近她,表示“我愿意和你建立連接”叉瘩。其中,SYN 的值是在第一次發(fā)送 SYN 請求時(shí)會值的基礎(chǔ)上自 +1 得到的粘捎,而 ACK 的值是在服務(wù)器 SYN 包中 Req 值的基礎(chǔ)上 +1薇缅,表示對服務(wù)器請求的一種響應(yīng)。
7:經(jīng)過 TCP 三次握手之后攒磨,客戶端與服務(wù)器已經(jīng)建立了 TCP 連接泳桦。此時(shí),客戶端在 TCP 連接的基礎(chǔ)上發(fā)送 HTTP GET
請求娩缰。其中請求行中的 /
表示要獲取服務(wù)器根目錄下的默認(rèn)文件灸撰。
8:服務(wù)器收到客戶端的 HTTP 請求后,會先在 TCP 層先進(jìn)行傳輸層的響應(yīng)拼坎,表示我已經(jīng)收到了客戶端發(fā)來的請求浮毯。同時(shí),請求被繼續(xù)向上傳遞給了應(yīng)用層的 80 端口演痒,丟給了 HTTP 服務(wù)進(jìn)行處理。
9:服務(wù)器對客戶端發(fā)過來的請求進(jìn)行處理后趋惨,將默認(rèn)首頁通過 Header + Body
的方式對客戶端的請求進(jìn)行了響應(yīng)鸟顺。
10:客戶端收到服務(wù)器的響應(yīng)后,先在 TCP 傳輸層對服務(wù)器進(jìn)行了響應(yīng),表示“我已經(jīng)收到了你的響應(yīng)”讯嫂;同時(shí)蹦锋,將響應(yīng)數(shù)據(jù)繼續(xù)向上傳遞給了應(yīng)用層的 5053 端口,丟給了 HTTP 客戶端進(jìn)行處理欧芽。
13:在 TCP 連接空閑了一段時(shí)間后莉掂,超過了 keep alive
所配置的超時(shí)時(shí)間后,客戶端通過發(fā)送 FIN 發(fā)起了斷開 TCP 的請求千扔,此時(shí)客戶端進(jìn)入 FIN_WAIT1
狀態(tài)憎妙,等待服務(wù)器應(yīng)答。
14:服務(wù)器收到客戶端發(fā)送過來的 FIN 斷開請求后曲楚,立即通過 ACK 響應(yīng)報(bào)文告訴客戶端厘唾,你的請求我已經(jīng)收到了,此時(shí)服務(wù)器處于 CLOSE_WAIT
狀態(tài)龙誊。
17:服務(wù)器發(fā)送 FIN 報(bào)文告訴客戶端自己也要斷開連接了抚垃,此時(shí),服務(wù)器處于 LAST_ACK
狀態(tài)趟大,等待客戶端的應(yīng)答鹤树。
18:客戶端收到服務(wù)器發(fā)過來的 FIN 斷開連接請求報(bào)文后,立即通過 ACK 應(yīng)答報(bào)文告訴客戶端逊朽,你的斷開請求我也已經(jīng)收到了罕伯。此時(shí),客戶端處于 TIME_WAIT
狀態(tài)惋耙,并等待一會兒來確保服務(wù)器收到 ACK 應(yīng)答報(bào)文后才進(jìn)入 CLOSED 狀態(tài)捣炬。而服務(wù)器收到客戶端發(fā)過來的 ACK 應(yīng)答報(bào)文后,就立即關(guān)閉了連接绽榛,處于 CLOSED 狀態(tài)湿酸。
整個(gè)通信的過程如下圖所示:
4.1.1 為什么 TCP 連接是三次握手?
這里主要考慮的是客戶端和服務(wù)器的發(fā)送能力和接收能力灭美⊥评#客戶端需要知道服務(wù)器同時(shí)具有發(fā)送數(shù)據(jù)的能力和接收并處理數(shù)據(jù)的能力;同樣的服務(wù)器也需要知道客戶端同時(shí)具有發(fā)送數(shù)據(jù)的能力和接收并處理數(shù)據(jù)的能力届腐。
第一個(gè) SYN 請求由客戶端發(fā)出铁坎,服務(wù)器收到客戶端的請求后,就知道了客戶端具有發(fā)送數(shù)據(jù)的能力犁苏;
第二個(gè) SYN + ACK
響應(yīng)由服務(wù)器發(fā)出硬萍,客戶端在收到服務(wù)器的響應(yīng)后,就知道了服務(wù)器具有發(fā)送數(shù)據(jù)的能力围详;同時(shí)朴乖,ACK 是對客戶端發(fā)送請求的處理和響應(yīng)祖屏,也就是說,客戶端收到 ACK 包后买羞,就知道了服務(wù)器具有處理數(shù)據(jù)的能力了袁勺。到這里服務(wù)器的兩個(gè)能力客戶端都已經(jīng)知道了,而此時(shí)服務(wù)器仍然只知道客戶端具有發(fā)送數(shù)據(jù)的能力畜普。
第三個(gè) ACK 包由客戶端發(fā)出期丰,服務(wù)器收到客戶端的響應(yīng)后,就知道了客戶端具有了接收并處理數(shù)據(jù)的能力吃挑。至此钝荡,服務(wù)器也知道了客戶端同時(shí)具有了發(fā)送數(shù)據(jù)和接收并處理響應(yīng)的能力。
4.1.2 什么是半連接隊(duì)列/全連接隊(duì)列儒鹿?
服務(wù)器第一次收到客戶端的 SYN 之后化撕,進(jìn)行處理后,并發(fā)送 SYN + ACK
請求響應(yīng)包到客戶端约炎,此時(shí)服務(wù)器就會處于 SYNC_RCVD
狀態(tài)植阴,此時(shí)雙方還沒有完全建立其連接,這個(gè)時(shí)候的 Socket 請求連接會被放在一個(gè)隊(duì)列里緩存起來圾浅,這種隊(duì)列就被稱為半連接隊(duì)列掠手。
TCP 重傳處理
服務(wù)器發(fā)送完 SYN + ACK
包后,如果未收到客戶端傳來的 ACK
包狸捕,服務(wù)器會進(jìn)行首次重傳喷鸽,等待一段時(shí)間后,會進(jìn)行二次重傳..... 直到重傳次數(shù)超過系統(tǒng)規(guī)定的最大重傳次數(shù)灸拍,系統(tǒng)將該連接從半連接隊(duì)列中移除做祝,重傳的等待時(shí)間,一般是指數(shù)增長的鸡岗,比如:1s混槐,2s,4s......
全連接隊(duì)列指的就是已經(jīng)完全三次握手轩性,建立連接的就會放在全連接隊(duì)列中声登。默認(rèn)情況下,全連接隊(duì)列滿了以后揣苏,服務(wù)器會忽略客戶端的 ACK悯嗓,隨后會重傳 SYN + ACK
,通過這種重傳的方式卸察,等待隊(duì)列有多余的空間存儲這個(gè) Socket 連接為止脯厨。當(dāng)然,也可以進(jìn)行配置坑质,改成當(dāng)全連接隊(duì)列滿后合武,由服務(wù)器端發(fā)送 SYN_RST
給客戶端个少,直接釋放資源。
4.1.3 三次握手會攜帶數(shù)據(jù)么眯杏?
當(dāng)客戶端發(fā)送 ACK 報(bào)文時(shí),是可以攜帶數(shù)據(jù)的壳澳,因?yàn)?ACK 報(bào)文發(fā)送出去之后岂贩,就已經(jīng)建立了 TCP 連接,而在此時(shí)攜帶數(shù)據(jù)巷波,可以一定程度上增長傳輸?shù)男省?/p>
為什么其它階段不能攜帶數(shù)據(jù)呢萎津?
如果在客戶端發(fā)送 SYN 包的時(shí)候就攜帶數(shù)據(jù),這個(gè)數(shù)據(jù)就需要被緩存到服務(wù)器內(nèi)存中抹镊,而這樣做就會有一個(gè)安全隱患:惡意程序只發(fā)送 SYN 包锉屈,而不發(fā)送 ACK 包,且在每個(gè) SYN 包中攜帶大量數(shù)據(jù)垮耳,這種情況下颈渊,就有可能會耗盡服務(wù)器的資源,而使其無法響應(yīng)正常的請求终佛。
什么是 SYN 攻擊俊嗽?
服務(wù)器發(fā)送完 SYN + ACK
包后,就會將當(dāng)前 Socket 連接放到半連接隊(duì)列中進(jìn)行緩存铃彰。攻擊者常常在短時(shí)間內(nèi)偽造大量不存在的 IP 地址绍豁,并不斷的向服務(wù)器 SYN 包,Server 則回復(fù)確認(rèn)包牙捉,并等待客戶端的 ACK 包竹揍,由于資源不存在,服務(wù)器會不斷的重試邪铲,直到超時(shí)玉雾,才將其從半連接隊(duì)列中移除辣苏。而由于客戶端在短時(shí)間內(nèi)發(fā)送了大量的 SYN 包,導(dǎo)致正常的 SYN 請求因?yàn)榘脒B接隊(duì)列滿了而被丟棄,從而拒絕了正衬踅客戶端的請求。SYN 攻擊就是一種典型的 Dos/DDos
拒絕服務(wù)攻擊喂击。
常用防御 SYN 攻擊的方法:
- 縮短 SYN 超時(shí)時(shí)間
- 增加最大半連接數(shù)
- 過濾網(wǎng)關(guān)防護(hù)
- SYN cookies 技術(shù)
4.1.4 為什么握手是三次昼榛,而揮手需要四次?
TCP 半關(guān)閉
TCP 半關(guān)閉指的是 TCP 提供了連接的一端在結(jié)束它的發(fā)送數(shù)據(jù)的能力后永丝,還能接收來自另外一端數(shù)據(jù)的能力锹漱。
TCP 四次揮手
TCP 三次握手只能由客戶端發(fā)起不同,四次握手可以由客戶端或服務(wù)器中的任意一端發(fā)起慕嚷。
四次握手的過程:
- A 端發(fā)起 FIN 報(bào)文哥牍,此時(shí) A 端處于
FIN_WAIT1
狀態(tài)毕泌,此狀態(tài)后,該端就停止再發(fā)送數(shù)據(jù)嗅辣,意思是 A 端關(guān)閉了發(fā)送數(shù)據(jù)的能力撼泛,并等待 B 端確認(rèn) - B 端收到 FIN 之后,會發(fā)送 ACK 報(bào)文澡谭,表示 B 端已經(jīng)收到了 A 端想要斷開連接的請求愿题。此時(shí) B 端處于
CLOSE_WAIT
狀態(tài)。此時(shí)蛙奖,TCP 處于半關(guān)閉狀態(tài)潘酗,等待 B 端發(fā)送 FIN 連接釋放報(bào)文段 - 如果 B 端也想斷開連接,和 A 端一樣雁仲,發(fā)送 FIN 報(bào)文仔夺,此時(shí),B 端處于
LAST_ACK
的狀態(tài)攒砖,表示服務(wù)器也停止了向客戶端發(fā)送數(shù)據(jù)缸兔,意思是 B 端關(guān)閉了發(fā)送數(shù)據(jù)的能力,并等待 A 端確認(rèn) - A 關(guān)收到 B 端發(fā)過來的 FIN 報(bào)文后吹艇,一樣發(fā)送一個(gè) ACK 報(bào)文作為應(yīng)答灶体,此時(shí),客戶端處于
TIME_WAIT
狀態(tài)掐暮,而不會立即關(guān)閉蝎抽,而是會等一會兒來確保 B 端收到 ACK 報(bào)文之后才進(jìn)入 CLOSED 狀態(tài)。而 B 端在收到 A 端發(fā)送的 ACK 應(yīng)答后路克,就立即關(guān)閉連接樟结,處于 CLOSED 狀態(tài)
為什么是四次揮手,而不是三次
當(dāng) A 端發(fā)送關(guān)閉請求的 FIN 報(bào)文時(shí)精算,B 端可能還有數(shù)據(jù)需要傳輸而不想馬上關(guān)閉連接瓢宦,所以就發(fā)送了一個(gè) ACK 應(yīng)答報(bào)文,表示我已經(jīng)收到了你想要關(guān)閉連接的請求灰羽。此時(shí)驮履,進(jìn)入半關(guān)閉狀態(tài),即 A 端已經(jīng)不會再發(fā)送數(shù)據(jù)廉嚼,而 B 可能還需要發(fā)送數(shù)據(jù)玫镐。
當(dāng) B 端發(fā)送完數(shù)據(jù)后,已經(jīng)沒有更多數(shù)據(jù)要發(fā)送的情況下怠噪,也會發(fā)送一個(gè) FIN 報(bào)文給 A 端恐似,表示我也沒有數(shù)據(jù)要發(fā)送了,咱們關(guān)閉連接吧傍念。A 端在收到 FIN 報(bào)文后矫夷,就立即發(fā)送了 ACK 應(yīng)答報(bào)文葛闷。B 端在收到 ACK 應(yīng)答報(bào)文后,就立即關(guān)閉了連接双藕,而 A 端在等待一段時(shí)間后淑趾,認(rèn)為 B 端已經(jīng)收到了 ACK 應(yīng)答報(bào)文的情況下,也關(guān)閉了連接忧陪。至此治笨,TCP 連接徹底斷開了。
為什么四次揮手時(shí)赤嚼,第四次發(fā)送了 ACK 包后的一端會進(jìn)入 TIME_WAIT 狀態(tài),而不是直接進(jìn)入 CLOSED 狀態(tài)
由于 TCP 協(xié)議是一種面向連接的傳輸方式顺又,必須保證數(shù)據(jù)能夠正確到達(dá)目標(biāo)機(jī)器更卒。如果最后一個(gè)發(fā)給服務(wù)器 ACK 包,由于網(wǎng)絡(luò)原因稚照,服務(wù)器未收到的話蹂空,此時(shí),服務(wù)器會再次重傳上一個(gè) FIN 包給客戶端果录。如果這時(shí)客戶端完全關(guān)閉了連接上枕,那么服務(wù)器永遠(yuǎn)都收不到 ACK 包了,所以弱恒,客戶端在發(fā)送 ACK 包后辨萍,要等待片刻,確認(rèn)對方收到 ACK 包(也就是不會再收到服務(wù)器重傳的 FIN 包)后才能進(jìn)入 CLOSED 狀態(tài)返弹。
那客戶端需要等待多久了锈玉?
數(shù)據(jù)包在網(wǎng)絡(luò)中是有生存時(shí)間的,超過這個(gè)時(shí)間還未到達(dá)目標(biāo)主機(jī)就會被丟棄义起,并通知源主機(jī)拉背。這個(gè)時(shí)間被稱為 報(bào)文最大生存時(shí)間(MSL,Maximum Segment Lifetime)默终。TIME_WAIT
通常要等待 2MSL 才進(jìn)入 CLOSED 狀態(tài)椅棺。這 2MSL 包括 ACK 包到達(dá)服務(wù)器需要的 1MSL 時(shí)間和服務(wù)器重傳 FIN 包也需要的 MSL 時(shí)間。 如果 2MSL 后還未收到服務(wù)器重傳的 FIN 包齐蔽,就說明服務(wù)器已經(jīng)收到了 ACK 包两疚。
疑問
在抓包的過程中,HTTP 請求響應(yīng)完成后含滴,客戶端在 2S 左右的時(shí)間內(nèi)鬼雀,就斷開了和服務(wù)器的 TCP 連接?
在抓包過程中蛙吏,四次揮手中的 FIN 發(fā)送方中為什么都有帶一個(gè) ACK 的確認(rèn)應(yīng)答源哩?
5. HTTP 報(bào)文結(jié)構(gòu)
5.1 HTTP 協(xié)議的基本組成
請求行
example:GET / HTTP/1.1
請求行的作用:描述客戶端想要怎樣操作服務(wù)器上的資源鞋吉。
狀態(tài)行
example:HTTP/1.1 200 OK
狀態(tài)行的作用:描述服務(wù)器的響應(yīng)狀態(tài)。
請求頭唯一必填字段
Host: www.example.com
Host 請求字段的作用:告訴服務(wù)器這個(gè)請求應(yīng)該由哪個(gè)主機(jī)處理励烦,當(dāng)一臺計(jì)算機(jī)(主要是多個(gè)域名對應(yīng)同一個(gè) IP 的情況)上托管了多個(gè)虛擬主機(jī)的時(shí)候谓着,服務(wù)器就需要使用 Host 字段來進(jìn)行“路由”。
5.2 常用請求方法
- GET:獲取資源坛掠,讀取或者下載數(shù)據(jù)
- HEAD:獲取資源的元信息赊锚,也就是只有響應(yīng)頭,而沒有實(shí)體 body屉栓。比如:檢查文件是否存在舷蒲;檢查文件是否有新版本等操作
- POST:向資源提交信息,相當(dāng)于寫入或上傳數(shù)據(jù)友多,數(shù)據(jù)放在報(bào)文的實(shí)體 body 里牲平,相比于 * PUT,POST 常常有“新建”的含義
- PUT:類似 POST域滥,相比于 POST纵柿,PUT 常常有“修改”的含義
- DELETE:刪除資源
- CONNECT:建立特殊的連接隧道,要求服務(wù)器為客戶端和另一臺遠(yuǎn)程服務(wù)器建立一條特殊的連接隧道启绰,此時(shí)昂儒,WEB 服務(wù)器充當(dāng)“代理”角色
- OPTIONS:列出對資源實(shí)行的方法
TRACE:追蹤請求/響應(yīng)的傳輸路徑
安全與冪等
在 HTTP 里的安全指的是:請求方法不會對服務(wù)器上的資源造成實(shí)質(zhì)的修改。
從上面的定義可以看出:
- 只有 GET 和 HEAD 是安全的委可,無論操作多少次渊跋,服務(wù)器上的資源都不會發(fā)生實(shí)質(zhì)的改變。
- POST/PUT/DELETE 是不安全的着倾,這三個(gè)方法會增加刹枉、修改或刪除服務(wù)器上的資源。
在 HTTP 里的冪等指的是:多次執(zhí)行相同的操作屈呕,結(jié)果也是一樣的微宝。即多次“冪”后也相等。
從定義可以看出:
- GET 和 HEAD 也是冪等的虎眨,DELETE 多次刪除同一個(gè)資源蟋软,結(jié)果也是“資源不存在”,所以也是冪等的嗽桩。
- 如果將 POST 嚴(yán)格定義為“新增或提交數(shù)據(jù)”岳守,多次提交數(shù)據(jù)就會創(chuàng)建多個(gè)資源,所以不是冪等的碌冶。而如果將 PUT 嚴(yán)格定義為“替換或更新數(shù)據(jù)”湿痢,多次更新數(shù)據(jù),其數(shù)據(jù)的狀態(tài)也還是第一次更新的狀態(tài),所以也是冪等的譬重。
5.3 常見狀態(tài)碼
- 1xx:提示信息拒逮,表示目前是協(xié)議處理的中間狀態(tài),還需要后續(xù)的操作
- 2xx:成功臀规,表示報(bào)文已經(jīng)收到并被正確處理
- 3xx:重定向滩援,資源位置發(fā)生變動,需要客戶端重新發(fā)送請求
- 4xx:客戶端錯(cuò)誤塔嬉,請求報(bào)文錯(cuò)誤玩徊,服務(wù)器無法處理
- 5xx:服務(wù)器錯(cuò)誤,服務(wù)器在處理請求時(shí)內(nèi)部發(fā)生了錯(cuò)誤
1xx 常見響應(yīng)碼
101:表示要在 HTTP 協(xié)議的基礎(chǔ)上改成其它協(xié)議繼續(xù)通信谨究,如:WebSocket恩袱,而如果服務(wù)器也同意的情況下,就會返回狀態(tài)碼 101胶哲,之后的數(shù)據(jù)傳輸就不用 HTTP 了畔塔。
2xx 常見響應(yīng)碼
- 200 OK:表示服務(wù)器處理成功并返回
- 204 NOT Content:表示服務(wù)器處理成功并返回,但是響應(yīng)數(shù)據(jù)中不包含 body 數(shù)據(jù)(與 200 的區(qū)別)
- 206 Partial Content:HTTP 分塊下載或斷點(diǎn)續(xù)傳的基礎(chǔ)纪吮,客戶端發(fā)送
Content-Range
請求、要求獲取資源的部分?jǐn)?shù)據(jù)時(shí)萎胰,服務(wù)器會通過 206 來進(jìn)行響應(yīng)碾盟,表示服務(wù)器成功處理其范圍請求
。
3xx 常見響應(yīng)碼
- 301 Moved Permanently:永久重定向技竟。表示當(dāng)前訪問的資源已經(jīng)不存在了冰肴,需要使用新的 URI 來進(jìn)行訪問
- 302 Moved Temporary:臨時(shí)重定向。表示訪問的資源還在榔组,但需要暫時(shí)用另一個(gè) URI 訪問
- 304 Not Modified:緩存重定向熙尉。一般在請求中使用
If-Modified-Since
字段后,用來表示資源未被修改搓扯,讓客戶端直接去緩存中獲取數(shù)據(jù)
301 和 302 的區(qū)別
- 對于搜索引擎來說检痰,如果是 302 的話,搜索引擎會抓取新的內(nèi)容而保留舊的地址锨推,因?yàn)樗阉饕嬲J(rèn)為新的網(wǎng)址是暫時(shí)的铅歼;而如果是 301 的話,搜索引擎在抓取新的內(nèi)容的同時(shí)换可,也將舊的網(wǎng)址替換為新的網(wǎng)址
- 對于客戶端緩存來說椎椰,如果是 302 的話,客戶端是不會緩存數(shù)據(jù)的沾鳄,每次請求都訪問原地址慨飘;而如果是 301 的話,客戶端會進(jìn)行緩存數(shù)據(jù)译荞,在緩存沒有過期的情況下瓤的,客戶端會使用緩存的數(shù)據(jù)休弃,而不會再去請求原地址
4xx 常見響應(yīng)碼
- 400 Bad Request:表示請求報(bào)文有錯(cuò)誤,但不清楚具體是什么錯(cuò)誤
- 403 Forbidden:表示服務(wù)器禁止客戶端請求該資源
- 404 Not Found:表示服務(wù)器沒有找到客戶端想要訪問的資源
5xx 常見響應(yīng)碼
- 500 Internal Server Error:表示服務(wù)器發(fā)生了錯(cuò)誤堤瘤,但不清楚具體是什么錯(cuò)誤
- 501 Not Implemented:表示客戶端請求的功能還不支持
- 502 Bad Gateway:通常表示服務(wù)器作為網(wǎng)關(guān)或代理服務(wù)器時(shí)返回的錯(cuò)誤碼玫芦,表示自己正常工作,而訪問后端服務(wù)器時(shí)發(fā)生了錯(cuò)誤
- 503 Service Unavailable:表示服務(wù)器當(dāng)前很忙本辐,暫時(shí)無法響應(yīng)請求
6. HTTP 特點(diǎn)
- 靈活可擴(kuò)展桥帆,用空格分隔單詞,用換行分隔字段
- 可靠傳輸慎皱。由 TCP 協(xié)議來保持其可靠傳輸
- 應(yīng)用層協(xié)議老虫。HTTP 幾乎可以傳遞一切東西,滿足各種需求茫多,稱得上是一個(gè)“萬能”的協(xié)議
- 請求-應(yīng)答通信模式祈匙。請求方主動發(fā)起連接和請求,應(yīng)答方只有在收到請求后才能被動的答復(fù)天揖,如果沒有請求夺欲,不會有任何答復(fù)
- 無狀態(tài)。在通信過程中今膊,兩端都不保存任何數(shù)據(jù)些阅,每次收發(fā)報(bào)文都是互相獨(dú)立的、沒有任何的聯(lián)系
HTTP 無狀態(tài)和 UDP 無狀態(tài)的區(qū)別
- HTTP 是有連接無狀態(tài)斑唬,順序發(fā)包順序收包市埋,按照報(bào)文順序管理報(bào)文
- UDP 是無連接無狀態(tài),順序發(fā)包亂序收包恕刘,數(shù)據(jù)包發(fā)出去后缤谎,就不管了
HTTP 的優(yōu)點(diǎn)
- 簡單、靈活褐着、易于擴(kuò)展
- 應(yīng)用廣泛
- 無狀態(tài)坷澡。不需要記錄額外的狀態(tài)信息,減輕了服務(wù)器的負(fù)擔(dān)含蓉;同時(shí)洋访,由于沒有差異也導(dǎo)致很容易組建集群,通過負(fù)載均衡將請求轉(zhuǎn)發(fā)到任意一臺服務(wù)器谴餐,不會因?yàn)闋顟B(tài)的不一致而導(dǎo)致處理出錯(cuò)
- 明文傳輸姻政。方便調(diào)試和分析
HTTP 的缺點(diǎn)
- 無狀態(tài)。無法支持多個(gè)步驟的“事務(wù)”操作岂嗓,每次請求都要攜帶身份驗(yàn)證信息汁展,增加了不必要的數(shù)據(jù)傳輸量。可以通過 Cookie 技術(shù)實(shí)現(xiàn)有狀態(tài)
- 明文傳輸食绿。毫無隱私可言侈咕,容易被窺視。如:免費(fèi) WIFI 陷阱
- 不支持?jǐn)?shù)據(jù)完整性校驗(yàn)器紧。數(shù)據(jù)在傳輸過程中耀销,容易被篡改而無法驗(yàn)證真?zhèn)?/li>
- 性能問題〔簦可能出現(xiàn)隊(duì)頭阻塞的問題
7. HTTP 實(shí)體數(shù)據(jù)
7.1 識別 HTTP 傳輸數(shù)據(jù)類型的方法
HTTP 中主要通過 MIME 頭字段來標(biāo)識傳輸數(shù)據(jù)的類型熊尉,同時(shí)通過 Encoding type
來標(biāo)識使用的哪種數(shù)據(jù)使用的哪種壓縮方法。
MIME
MIME 格式:type/subtype
常見的幾種 MIME 類型:
- text/html掌腰,超文本文檔
- image/圖片格式
- audio/video狰住,音視頻數(shù)據(jù)
- application/類型,(如:application/json,application/pdf...)數(shù)據(jù)不固定齿梁,可能是文本或二進(jìn)制催植,需要由上層應(yīng)用程序來解釋
Encode type
- GZIP
- Deflate
- br:一種專門為 HTTP 優(yōu)化的新壓縮算法
傳輸內(nèi)容類型協(xié)商方法
Accept:客戶端使用 Accept 頭告訴服務(wù)端希望接收什么樣的數(shù)據(jù)
Content:服務(wù)器通過 Content 告訴客戶端實(shí)際傳輸?shù)氖鞘裁搭愋偷臄?shù)據(jù)
7.2 HTTP 傳輸大文件的方法
- 數(shù)據(jù)壓縮,使用 GZIP 等壓縮方式對 body 數(shù)據(jù)進(jìn)行壓縮
- 分塊傳輸勺择,由服務(wù)器將大文件分解成多個(gè)小塊分批發(fā)送給瀏覽器创南,瀏覽器收到后再組裝還原
- 范圍請求,由客戶端發(fā)起省核,表示只想請求大文件的某一部分的數(shù)據(jù)(如:看電影時(shí)拖動進(jìn)度條)稿辙。服務(wù)器通過使用
Accept-Ranges: bytes
告訴客戶端自己是支持范圍請求的。請求頭使用Range: bytes=x-y
(x 和 y 分別表示范圍的開頭和結(jié)尾芳撒,單位為 byte) - 多段數(shù)據(jù)邓深,實(shí)際上也是一種范圍請求未桥,只是在請求頭里面同時(shí)添加了多個(gè)范圍笔刹,如:
Range: bytes=x-y,a-b,c-d
。其響應(yīng)頭中對應(yīng)的 MIME 類型為:multipart/byteranges
冬耿,其報(bào)文結(jié)構(gòu)也與單個(gè)的范圍請求有所區(qū)別舌菜。
HTTP 如何分塊傳輸
服務(wù)器使用響應(yīng)頭字段 Transfer-Encoding: chunked
來標(biāo)識數(shù)據(jù)是分塊傳輸?shù)摹?/p>
Transfer-Encodding: chunked 和 Content-length 的關(guān)系
- 這兩個(gè)字段都是響應(yīng)頭字段
- 兩個(gè)響應(yīng)字段是互斥的,不能同時(shí)出現(xiàn)
分塊結(jié)構(gòu)
- 每個(gè)分塊由長度頭和數(shù)據(jù)塊兩部分組成
- 長度頭或數(shù)據(jù)塊都是以 CRLF(回車換行作為結(jié)尾)
- 最后用一個(gè)長度為 0 的塊表示結(jié)束亦镶,即:0\r\n\r\n日月,其中,第一個(gè) \r\n 表示長度頭的結(jié)尾缤骨,第二個(gè) \r\n 表示數(shù)據(jù)塊的結(jié)尾爱咬,由于數(shù)據(jù)塊中沒有數(shù)據(jù),所以绊起,兩個(gè) \r\n 就連在一起了
=== chunked 實(shí)驗(yàn) 16-1 使用 Putty 訪問
Range 的格式
開頭或結(jié)尾中的任意一個(gè)都可以省略精拟,但不可以同時(shí)省略。如:
- "0-":表示從文檔起點(diǎn)到終點(diǎn),如果文檔有 200 個(gè)字節(jié)蜂绎,相當(dāng)于 0-199栅表;
- "10-":表示從 第 10 個(gè)字節(jié)到文檔末尾;
- "-1":表示文檔的倒數(shù)第一個(gè)字節(jié)师枣,也就是最后一個(gè)字節(jié)到文檔結(jié)尾怪瓶;
- "-10":表示從文檔末尾倒數(shù) 10 個(gè)字節(jié)到文檔結(jié)尾;
服務(wù)器 Range 響應(yīng)
服務(wù)器使用 Content-Range: bytes x-y/length
對 Range
請求進(jìn)行響應(yīng)践美。這里的 x 和 y 表示服務(wù)器當(dāng)前響應(yīng)的范圍區(qū)間洗贰,length 表示數(shù)據(jù)的總長度。
服務(wù)器響應(yīng) Range 異常
如果超出范圍拨脉,則返回狀態(tài)碼 416哆姻,意思是“你請求的范圍有誤”
===== Range 范圍請求實(shí)驗(yàn) 16-2
多段數(shù)據(jù)響應(yīng)的報(bào)文結(jié)構(gòu)
===== 多段數(shù)據(jù)范圍請求實(shí)驗(yàn) 16-2
8. HTTP 連接管理
8.1 短連接
一次請求-響應(yīng)后就會斷開連接。
短連接存在問題
因?yàn)?TCP 建立連接和關(guān)閉連接是非趁蛋颍“昂貴”的操作矛缨,建立連接要有“三次握手”,需要耗費(fèi) 1 個(gè) RTT(Round-Trip Time帖旨,往返延時(shí))箕昭;關(guān)閉連接是“四次揮手”,4 個(gè)數(shù)據(jù)需要 2 個(gè) RTT解阅。
8.2 長連接
HTTP/1.1 中長連接默認(rèn)是開啟的落竹,
服務(wù)器主動關(guān)閉長連接的策略
- 使用 “keepalive-timeout” 指令,設(shè)置連接超時(shí)時(shí)間货抄,如果超過這個(gè)時(shí)間都沒有任何數(shù)據(jù)收發(fā)就關(guān)閉連接
- 使用 “keepalive-requests” 指令述召,設(shè)置長連接上可以發(fā)送的最大請求次數(shù),如果超過最大請求次數(shù)則會斷開長連接
8.3 隊(duì)頭阻塞
HTTP 的請求-應(yīng)答通信模型蟹地,決定了請求是一發(fā)一收的串行通信方式积暖,所有包只有入隊(duì)的順序,排在前面的會先被處理怪与,沒有優(yōu)先級的概念夺刑。如果隊(duì)首由于處理的太慢耽誤了時(shí)間,就會使得其它請求不得不跟著一起等待分别。
8.3 HTTP 性能優(yōu)化
- 并發(fā)連接遍愿,同時(shí)對一個(gè)域名發(fā)起多個(gè)長連接。
- 域名分片耘斩,將訪問同一個(gè)域名的請求分?jǐn)偟讲煌?IP 地址的服務(wù)器上沼填。
9. HTTP 重定向
9.1 重定向的響應(yīng)頭字段
Location: /index.html
。
對應(yīng)的值即可以指定絕對 URI括授,還可以指定相對 URI坞笙。
如果使用絕對 URI 的話轧邪,需要帶上 http://
頭,否則會被當(dāng)作相對路徑處理羞海。
10. HTTP Cookie 機(jī)制
10.1 Cookie 的作用
讓 HTTP 這種無狀態(tài)的協(xié)議通過 Cookie 機(jī)制保存相應(yīng)的狀態(tài)忌愚。通過在客戶端緩存一些狀態(tài)信息,并在客戶端請求時(shí)却邓,攜帶這些狀態(tài)信息來實(shí)現(xiàn) HTTP 有狀態(tài)的目的硕糊。
10.2 Cookie 的工作過程
- 當(dāng)用戶通過瀏覽器第一次訪問服務(wù)器時(shí),服務(wù)器會為該瀏覽器創(chuàng)建一個(gè)獨(dú)特的身份標(biāo)識腊徙,格式為
key=value
简十。并將其放到set-cookie
字段里返回給瀏覽器。 - 瀏覽器收到報(bào)文后撬腾,將
set-cookie
的值保存了起來螟蝙,并在下次請求的時(shí)候,主動將這個(gè) Cookie 放入到請求頭中一并發(fā)送給服務(wù)器民傻。 - 通常情況下胰默,服務(wù)器會通過多個(gè)
set-cookie
頭字段來返回多條Cookie
信息給瀏覽器。而瀏覽器在向服務(wù)器發(fā)送請求時(shí)漓踢,只需要通過;
將多個(gè)key-value
的鍵值隔開并放到同一個(gè)Cookie
請求頭字段即可牵署。
Cookie 是由瀏覽器來維護(hù)的,所以喧半,其作用范圍在各種瀏覽器內(nèi)部奴迅。使用其它瀏覽器則需要重新保存 Cookie。
10.3 Cookie 的常用屬性
- Expires:過期時(shí)間挺据,是一個(gè)絕對時(shí)間點(diǎn)取具,可以理解為
截止日期
。 - Max-Age:相對時(shí)間點(diǎn)扁耐,單位是“秒”暇检。瀏覽器使用最后一次收到報(bào)文的時(shí)間點(diǎn) + Max-Age,就等于失效的絕對時(shí)間做葵。
- Exprices 和 Max-Age 同時(shí)被設(shè)置時(shí)占哟,會優(yōu)先采用
Max-Age
的相對時(shí)間點(diǎn)心墅。 - Domain 和 path 用來指令 Cookie 所屬于的域名和路徑酿矢,也就是指令 Cookie 的作用域,只會在對應(yīng)的域名和路徑都匹配的時(shí)候怎燥,瀏覽器才會攜帶該 Cookie瘫筐。作用域可以針對每個(gè)
set-cookie
來進(jìn)行單獨(dú)配置。如果沒有指定作用域的情況下铐姚,當(dāng)前域名下的所有請求中都攜帶這個(gè)Cookie
值策肝。 - HttpOnly:告訴瀏覽器肛捍,該 Cookie 只能通過 HTTP 協(xié)議傳輸。
- sameSite:設(shè)置 Cookie 是否允許隨著跳轉(zhuǎn)鏈接跨站發(fā)送
- Secure:表示這個(gè) Cookie 僅能用 HTTP 協(xié)議加密傳輸之众,但 Cookie 保存本身不是加密的拙毫,仍然是以明文的形式存儲。
10.4 Cookie 的典型應(yīng)用
- 身份認(rèn)證
- 廣告跟蹤棺禾,通過使用第三方 Cookie 來實(shí)現(xiàn)缀蹄,而非主站 Cookie。如果廣告商覆蓋范圍廣膘婶,你訪問的很多網(wǎng)站都集成了該廣告商的廣告后缺前,你走到哪里都會認(rèn)出你,然后悬襟,給你推送廣告衅码。
====== Cookie 失效時(shí)間和作用域 19-2
11. HTTP 緩存
11.1 HTTP 緩存工作流程
- 瀏覽器發(fā)現(xiàn)緩存無數(shù)據(jù),于是發(fā)送請求脊岳,向服務(wù)器獲取資源
- 服務(wù)器響應(yīng)請求逝段,返回資源,同時(shí)標(biāo)記資源的有效期
- 瀏覽器緩存資源割捅,等待下次重用
11.2 Cache-Control 緩存字段
服務(wù)器使用 Cache-Control: max-age=50
字段來對資源進(jìn)行緩存控制惹恃,值為 key-value
鍵值對格式。
max-age
max-age
是 HTTP 緩存控制常用的屬性棺牧,常見的值有:
- no-store:不允許緩存巫糙。例如:秒殺頁面
- no-cache:不是不能緩存,而是可以緩存颊乘,只是使用之前要去服務(wù)器驗(yàn)證一下是否已經(jīng)過期参淹,是否有最新版本
- must-revaliable:表示如果緩存沒有過期則可以繼續(xù)使用,但過期了如果還想用就需要去服務(wù)器驗(yàn)證
客戶端同樣可以使用 Cache-Control
字段來控制是否使用緩存乏悄。
刷新按鈕
當(dāng)點(diǎn)擊瀏覽器“刷新按鈕”時(shí)浙值,瀏覽器會在請求頭中添加 Cache-Control: max-age=0
字段,由于 max-age=0
說明瀏覽器不會使用緩存檩小,而是向服務(wù)器發(fā)請求开呐,服務(wù)器看到 max-age=0
,所以會重新生成最新的報(bào)文返回給瀏覽器规求。
Ctrl+F5 強(qiáng)制刷新
當(dāng)使用 Ctrl + F5
強(qiáng)制刷新時(shí)筐付,瀏覽器會在請求頭中添加 Cache-Control: no-control
頭字段,處理效果基本上和刷新按鈕一樣阻肿。
瀏覽器默認(rèn)不使用緩存
當(dāng)服務(wù)器通過 Cache-Control: max-age=30
字段返回緩存時(shí)瓦戚,瀏覽器默認(rèn)不會使用緩存,而是使用 Cache-Control: max-age=0
請求頭字段去請求服務(wù)器獲取最新的數(shù)據(jù)丛塌。那緩存如何還會被使用呢较解?
- 當(dāng)瀏覽器點(diǎn)擊前進(jìn)畜疾、后退或頁面跳轉(zhuǎn)操作時(shí),瀏覽器才會去訪問緩存里的數(shù)據(jù)(也就是 from disk cache)
===== Cache-Control 實(shí)驗(yàn) 20-1
11.3 條件請求 If-Modified-Since/Last-Modified 或 If-None-Match/ETag
ETag:表示資源的唯一標(biāo)識印衔,剛資源被修改后啡捶,值會跟著改變。
Last-Modified:資源最后修改時(shí)間奸焙。
If-Modified-Since 和 Last-Modified 的工作流程
- 瀏覽器發(fā)送請求届慈,服務(wù)器響應(yīng)請求,并在響應(yīng)頭里添加了
Last-Modified: 修改時(shí)間
字段來標(biāo)識當(dāng)前資源的最后修改時(shí)間(如果是動態(tài)生成的網(wǎng)頁忿偷,由于每次都是新生成的金顿,所以,不會訪問緩存)鲤桥,瀏覽器緩存Last-Modified
時(shí)間 - 瀏覽器二次對同一資源發(fā)起請求揍拆,并在請求頭中添加
If-Modified-Since: Last-Modified
字段給服務(wù)器 - 服務(wù)器收到請求后,和對應(yīng)資源的最后修改時(shí)間作比較茶凳,如果相等嫂拴,則返回 304,讓瀏覽器去本地獲取數(shù)據(jù)贮喧;如果不相等筒狠,就會把最新的資源文件及其 Last-Modified 返回給瀏覽器
If-None-match/ETag
- 瀏覽器發(fā)送請求,服務(wù)器響應(yīng)請求箱沦,并在響應(yīng)頭里添加了 ETag 字段來標(biāo)識當(dāng)前資源的唯一標(biāo)識辩恼,瀏覽器緩存 ETag 標(biāo)識
- 瀏覽器二次對同一資源發(fā)起請求,并在請求頭中添加了
If-None-Match: ETag
頭字段發(fā)送給服務(wù)器 - 服務(wù)器收到請求后谓形,與本地資源的 ETag 值進(jìn)行比較灶伊,如果相等,則返回 304寒跳,讓瀏覽器去本地獲取數(shù)據(jù)聘萨;如果不相等,就會把最新的資源文件及其 ETag 返回給瀏覽器
12. HTTP 代理
12.1 什么是代理服務(wù)
代理服務(wù)指:服務(wù)器本身不生產(chǎn)內(nèi)容童太,而是處于中間位置轉(zhuǎn)發(fā)上下游的請求和響應(yīng)米辐,具有雙重身份。面向下游用戶時(shí)书释,表現(xiàn)為服務(wù)器翘贮,代表源服務(wù)器響應(yīng)客戶端請求;面向上游的源服務(wù)器時(shí)征冷,又表現(xiàn)為客戶端择膝,代表客戶端發(fā)送請求誓琼。
12.2 代理服務(wù)器的作用
- 負(fù)載均衡检激。代理服務(wù)器可以通過將請求轉(zhuǎn)發(fā)到不同的服務(wù)器(不同的 IP 地址)來實(shí)現(xiàn)負(fù)載均衡肴捉。常用的負(fù)載均衡方法有輪詢、一致性哈希算法等叔收。
- 健康檢查齿穗。通過“心跳”等方式監(jiān)控后端服務(wù)器,并在發(fā)現(xiàn)故障時(shí)及時(shí)將其踢出群饺律,保證服務(wù)的高可用窃页。
- 安全防護(hù)。保護(hù)被代理的后端服務(wù)器复濒,限制 IP 地址或流量脖卖,抵御網(wǎng)絡(luò)攻擊和過載。
- 加密卸載巧颈。對外使用 SSL/TSL 加密通信認(rèn)證畦木,而在安全內(nèi)網(wǎng)不加密,消除服務(wù)器的解密成本砸泛。
- 數(shù)據(jù)過濾十籍。通過策略對上下行數(shù)據(jù)進(jìn)行過濾。
- 內(nèi)容緩存唇礁。暫存勾栗、復(fù)用服務(wù)器響應(yīng)。
12.3 代理相關(guān)頭字段
Via
在請求頭或響應(yīng)頭中都會出現(xiàn)盏筐。每經(jīng)過一個(gè)代理服務(wù)器围俘,代理服務(wù)器都會在請求或響應(yīng)頭里將自身信息(如:主機(jī)名或域名)追加到 via 字段的末尾。
作用:為了讓客戶端或源服務(wù)器感知到代理服務(wù)器的存在琢融,但不知道對方的真實(shí)信息(如:服務(wù)器或客戶端 IP)楷拳。
但一般來說,服務(wù)器的 IP 的需要保密的吏奸,是不會讓客戶端知道的欢揖。但是通常情況下,服務(wù)器需要知道客戶端的 IP 地址奋蔚,方便訪問控制她混、用戶畫像、統(tǒng)計(jì)分析等泊碑。
X-Forwarded-For 和 X-Real-IP
HTTP 協(xié)議里并沒有定義代理服務(wù)器轉(zhuǎn)發(fā)過程中添加 IP 地址的字段坤按。但是 X-Forwarded-For
和 X-Real-IP
已經(jīng)成為了事實(shí)上的標(biāo)準(zhǔn)。
X-Forwarded-For
: 在客戶端請求過程中馒过,每經(jīng)過一個(gè)結(jié)點(diǎn)就會通過在該字段上追加當(dāng)前結(jié)點(diǎn)的 IP(包括客戶端)臭脓。所以,最左邊的就是客戶端的 IP腹忽。
X-Real-IP
:該字段只是用于記錄客戶端的 IP 地址来累,經(jīng)過的代理服務(wù)器 IP 并不會被追加砂轻。是 X-Forwarded-For
的簡化版本蛤袒。
====== 代理服務(wù)器信息標(biāo)記實(shí)驗(yàn) 21-1萍程。
代理服務(wù)器轉(zhuǎn)發(fā)請求過程
- 客戶端通過 55061 端口與代理服務(wù)器通過三次握手來建立 TCP 連接阀湿。
- 建立 TCP 連接后,客戶端向服務(wù)器發(fā)送 GET 請求领猾。
- 代理服務(wù)器不產(chǎn)生內(nèi)容米同,所以通過 55063 端口通過 TCP 三次握手建立連接。
- 代理服務(wù)器連接源服務(wù)器成功后摔竿,發(fā)送了一個(gè)
HTTP/1.0
的 GET 請求面粮。 - 源服務(wù)器響應(yīng)了代理服務(wù)器,并且由于代理服務(wù)器使用的是
HTTP/1.0
继低,所以響應(yīng)后就立即通過四次揮手?jǐn)嚅_了與代理服務(wù)器的連接但金。 - 代理服務(wù)器收到源服務(wù)器響應(yīng)后,將其轉(zhuǎn)發(fā)給了客戶端郁季,完成一次代理服務(wù)冷溃。
X-Forward-For 給代理服務(wù)器帶來的問題
因?yàn)橥ㄟ^ X-Forwarded-For
操作代理信息必須要解析 HTTP 報(bào)文頭,這對于代理來說成本比較高梦裂,原本只需要簡單地轉(zhuǎn)發(fā)消息就好似枕,而現(xiàn)在卻必須要費(fèi)力解析數(shù)據(jù)再修改數(shù)據(jù),會降低代理的轉(zhuǎn)發(fā)性能年柠。
12.4 代理協(xié)議
代理協(xié)議也不是 HTTP 定義的凿歼,而是由知名代理軟件 HAProxy 所定義的,也是一個(gè)“事實(shí)標(biāo)準(zhǔn)”冗恨。
PROXY TCP4 1.1.1.1 2.2.2.2 55555 80\r\n
GET / HTTP/1.1\r\n
Host: www.xxx.com\r\n
\r\n
代理協(xié)議的定義是在 HTTP 的請求行前添加一個(gè)以 PROXY
開頭的信息行答憔。
好處
代理服務(wù)器收到報(bào)文后,只需要解析第一行就可以拿到客戶端地址掀抹,不需要再去理會后面的 HTTP 數(shù)據(jù)虐拓。
13. 緩存代理
13.1 什么是緩存代理
緩存代理就是支持緩存控制的代理服務(wù)。HTTP 服務(wù)器的緩存功能主要由代理服務(wù)器來實(shí)現(xiàn)傲武。
作用
可以讓請求不必走完整個(gè)后續(xù)處理流程蓉驹,“就近”獲得響應(yīng)結(jié)果。