本文為原創(chuàng)文章,如需轉載請注明出處夜涕,謝謝!
概述
1.TCP 為什么要三次握手和四次揮手
2.Http 知識簡單總結文中將使用 Client 和 Server 代表客戶端和服務端
一廷支、TCP 三次握手建立連接
還是先盜張圖瓦呼,無圖無真相划咐。
1.初始狀態(tài)
一開始的狀態(tài)比較簡單熟史,Server 打開進程并處于 LISTEN(收聽)狀態(tài)箱熬,隨時準備處理 Client 的連接請求类垦。Client 主動打開進程狈邑,準備發(fā)送第一條報文。
2. Client 發(fā)出連接請求 (第一次握手)
在打算建立 TCP 連接時蚤认,Client 向 Server 發(fā)出連接請求報文米苹,這時首部中的同部位 SYN=1,同時選擇一個初始序號 seq=x砰琢。TCP 規(guī)定蘸嘶,SYN 報文段不可攜帶數(shù)據(jù),但要消耗一個序號(seq)陪汽。這時训唱,TCP 客戶進程進入 SYN-SENT(同步已發(fā)送)狀態(tài)。
3.Server 發(fā)送確認報文 (第二次握手)
Server 收到建立連接請求后挚冤,如果同意建立連接况增,則向 Client 發(fā)送確認報文。確認報文中 SYN 位和 ACK 位都置為1训挡,同時也選擇一個初始序號 seq=y澳骤。注意,這個報文段也不能攜帶數(shù)據(jù)澜薄,但同樣要消耗一個序號为肮。這時 Server 進程進入 SYN-RCVD(同步收到)狀態(tài)。
4.Client 再次發(fā)送確認報文 (第三次握手)
Client 收到 Server 的確認報文后表悬,還需再向 Server 發(fā)出確認。確認報文 ACK=1丧靡,確認號 ack=y+1蟆沫,自己的序號 seq=x+1。TCP 的標準規(guī)定温治,ACK 報文段可以攜帶數(shù)據(jù)饭庞,如果不攜帶數(shù)據(jù)的話則不消耗序號,在這種情況下熬荆,下一個數(shù)據(jù)報文段的序號仍是 seq=x+1舟山。到此時,TCP 連接已經(jīng)建立完畢卤恳,Client 進入 ESTABLISHED(已建立連接)狀態(tài)累盗。Server 收到 Client 的確認報文后,也進入 ESTABLISHED 狀態(tài)突琳。
5.補充
- 四次握手:
在第二次握手中若债,Server 給 Client 發(fā)送的報文段,也可拆為兩個報文段拆融,先發(fā)送確認報文(ACK=1蠢琳,ack=x+1)啊终,然后再發(fā)送同步報文段(SYN=1,seq=y)傲须,這樣的過程就是四報文握手蓝牲,但效果是一樣的。
- 為什么要進行第三次握手泰讽?
主要是為了防止失效的連接請求報文又發(fā)送到 Server例衍,因而產(chǎn)生錯誤。
下面具體說說這種情況菇绵,Client 向 Server 發(fā)出連接請求報文肄渗,但是報文在途中丟失了,沒能收到 Server 的確認報文咬最,于是 Client 就又發(fā)送了一次連接請求翎嫡,這次連接正常,數(shù)據(jù)傳輸完畢后永乌,斷開了 TCP 連接惑申。
假設上述情況的第一次連接請求報文沒有丟失,而是由于網(wǎng)絡節(jié)點長時間滯留了翅雏,導致延誤到連接釋放后的某個時間才到達 Server圈驼。這時 Server 會再次給 Client 發(fā)送確認報文(第二次握手),但是 Client 進程程序并不會理睬確認報文望几,因為 Client 沒有發(fā)送連接請求〖ù啵現(xiàn)在假如沒有第三次握手就會建立連接,那么這次滯后的連接請求報文就會導致 TCP 誤建立連接橄抹,而 Client 卻不知已經(jīng)建立連接靴迫,并不會發(fā)送數(shù)據(jù)給 Server,這樣 Server 就會一直處于等待狀態(tài)楼誓,這樣就白白浪費了 Server 的很多資源玉锌。但有了第三次握手就會避免這種問題的發(fā)生,雖然延遲的連接請求發(fā)送到了 Server疟羹,但 Client 不會處理 Server 的確認報文主守,也不會再次發(fā)送確認請求報文,這樣 Server 就知道了 Client 并沒有真正想建立連接榄融。
二参淫、TCP 四次揮手釋放連接
從圖中可以看到,Client 和 Server 在已連接的狀態(tài)下開始進行數(shù)據(jù)傳輸愧杯,待傳輸結束后黄刚,開始四次握手釋放連接。
1.Client 發(fā)送釋放連接請求 (第一次握手)
首先民效,Client 發(fā)送釋放連接報文請求憔维,報文首部的終止控制位 FIN 置 1涛救,序號 seq=u,它等于之前已傳送的最后一個數(shù)據(jù)報文的序號 +1业扒。這時 Client 進入 FIN-WAIT-1 狀態(tài)检吆,等待 Server 確認。
2.Server 發(fā)送確認報文 (第二次握手)
這步和連接時相同程储,只是報文序號 seq=v蹭沛,它也等于之前發(fā)送的最后數(shù)據(jù)的序號 +1,ack=u+1章鲤。此時摊灭,TCP 進入半關閉狀態(tài),即 Client 已經(jīng)沒有數(shù)據(jù)再向 Server 發(fā)送了败徊,而 Server 也只有最后一些數(shù)據(jù)要發(fā)送給 Client帚呼。同時,Client 收到確認報文后皱蹦,會進入FIN-WAIT-2 狀態(tài)煤杀。
3.Server 發(fā)送釋放連接報文 (第三次握手)
Server 發(fā)送完最后的數(shù)據(jù)后,和 Client 第一次握手時一致沪哺,發(fā)送釋放連接報文沈自,F(xiàn)IN=1,seq=w辜妓,序號同樣是上一次數(shù)據(jù)報文的序號 +1(半關閉狀態(tài)時發(fā)送的數(shù)據(jù))枯途,ack=u+1。這時籍滴,Server 進入 LAST-ACK(最后確認狀態(tài))酪夷,等待 Client 最后的確認報文。
4.Client 發(fā)送最后的確認報文 (第四次握手)
最后 Client 發(fā)送確認報文异逐,ACK=1,seq =u+1 (上一次是 u捶索,TCP 規(guī)定即使 FIN 報文不攜帶數(shù)據(jù)也要消耗一個序號),ack=w+1插掂。之后 Client 進入 TIME-WAIT狀態(tài)灰瞻,此時連接還沒釋放,必須經(jīng)過時間等待計時器設置的時間 2MSL 后辅甥,Client 才進入 CLOSED 狀態(tài)酝润。時間 MSL 叫做最長報文段壽命
,RFC 793建議設為 2 分鐘璃弄。也就是說 Client 需要等待4分鐘后才可以真正關閉連接然后再去建立下一個連接要销。
5.補充
為什么 Client 需要等待 2MSL?
(1)假如 Client 最后的 ACK 報文段丟失了夏块,這時 Server 就會重新發(fā)送 FIN+ACK 報文給 Client疏咐,如果 Client 不等待 2MSL 直接關閉連接纤掸,那么 Server 就會一直處于 LAST-ACK 狀態(tài),造成了 Server 的資源浪費浑塞。而等待 2MSL借跪,Client 就會再次收到 Server 的 FIN+ACK 報文,然后重新給 Server 發(fā)送 ACK 報文酌壕,確保雙方都確認要關閉連接掏愁。
(2)假如 ACK 報文段沒有丟失,也是在網(wǎng)絡中滯留了卵牍,這 2MSL 的等待時間可以讓滯留的報文傳到 Server果港,保證本連接持續(xù)的時間內(nèi)所生產(chǎn)的報文都從網(wǎng)絡中消失,以免影響下一次連接糊昙。還有如果不等待 2MSL 辛掠,報文滯留也可能導致 Server 資源浪費,原因同 (1)溅蛉。
三公浪、 HTTP
1.HTTP 的請求過程
- 建立 TCP 連接
- Client 發(fā)送請求報文
- Server 發(fā)送響應報文
- 釋放 TCP 連接
可以看到 HTTP 是完全基于 TCP 連接的應用層協(xié)議,HTTP 所做的只是規(guī)定 Client 和 Server 需要遵循一定的規(guī)則來傳輸報文船侧,而 HTTP 本身是無連接的
欠气。
2.HTTP/1.0 和 HTTP/1.1
首先來看一張圖,圖中表示了一次 HTTP 請求所用的時間镜撩。其中 RTT(Round-Trip Time) 表示往返時間预柒,就簡單理解為時間開銷,我們看到 TCP 建立連接就需要一個 RTT袁梗,然后 HTTP 請求和響應總共需要一個 RTT宜鸯。知道了一次 HTTP 的時間開銷后,就可以說說 HTTP 1.0 和 1.1的特性了遮怜。
HTTP/1.0:非持續(xù)連接淋袖,即每次請求都要建立 TCP 連接,然后再去請求報文锯梁,所以每次都會消耗 2*RTT即碗,這種方式會使得服務器的負擔很重。
-
HTTP/1.1:解決了 1.0 的不足陌凳,采用了持續(xù)連接剥懒,即一次請求后仍然保持著這次連接,使同一個 Client 和 Server 可以繼續(xù)在這條連接上傳送 HTTP 報文合敦。HTTP/1.1 還有兩種工作方式初橘,
非流水線方式和流水線方式
。(1)非流水線方式:Client 收到前一個響應后才能發(fā)出下一個請求,類似于我們編程中的同步保檐。這種方式的缺點就是 Server 發(fā)送完一個對象后耕蝉,其 TCP 連接就處于空閑狀態(tài),浪費了資源夜只。
(2)流水線方式:同樣解決了非流水線的缺點赔硫,Client 可以連續(xù)向 Server 發(fā)出請求,然后陸續(xù)收到 Server 的響應盐肃,這樣服務器可連續(xù)響應爪膊,讓 TCP 空閑時間減少,提高了文檔下載效率砸王。
更新
HTTP 的請求方法
這里只介紹幾種常用的方法
GET:獲取服務器的某一處資源
POST:起初是為了向服務器輸入數(shù)據(jù)的推盛,但通常用于提交某些數(shù)據(jù)給服務器,然后服務器處理后返還給客戶端谦铃。
PUT:與 GET 相反耘成,是向服務器寫入某個資源,或用于修改更新服務器的資源驹闰,由于 PUT 可更改服務器數(shù)據(jù)瘪菌,所以需要密碼登錄來進行認證。
DELETE:刪除服務器的某一處資源嘹朗,不一定會請求成功师妙,HTTP 規(guī)范允許服務器在不通知客戶端的情況下撤銷請求。
好了屹培,4種方法的概念介紹完了默穴,接下來說一下最常用的 GET 和 POST,面試官常會問 GET 和 POST 有什么區(qū)別褪秀。具體內(nèi)容參考這篇GET 和 POST 的本質(zhì)區(qū)別蓄诽,在本文中我就總結一下結論。
GET 和 POST 本質(zhì)上都是基于TCP傳輸數(shù)據(jù)媒吗。GET 每次請求發(fā)送一個 TCP 包仑氛,包括 header 和 data。POST 每次請求發(fā)送 2 個 TCP 包闸英,先發(fā)送 header 告知服務器锯岖,然后再發(fā)送 data。
造成兩者有差異的原因是 HTTP 規(guī)范和瀏覽器和服務器的限制自阱,比如你在 GET 請求報文中包含了請求實體嚎莉,雖然數(shù)據(jù)傳送到了服務器米酬,但有可能服務器只處理 URL 中的參數(shù)沛豌,并不理會請求體中的內(nèi)容。