「三次握手,四次揮手「作為當代文明青年怎麼能不會【計網】

2022-01-05 20:00:02

👨‍🎓博主主頁爪哇貢塵拾Miraitow
📆傳作時間:🌴2022年1月4日🌴
📒內容介紹:最近在學習計算機網路所以會時不時更新有關內容
📚參考資料:王道考研計算機網路 度娘
🔗參考連結:👉TCP報文段的首部格式
⏳簡言以勵:列位看官,且將新火試新茶,詩酒趁年華
📝內容較多有問題希望能夠不吝賜教🙏
🎃 歡迎點贊 👍 收藏 ⭐留言 📝

在這裡插入圖片描述

TCP的三次握手和四次揮手,可以說是老生常談的經典問題了,通常也作為各大公司常見的面試考題,我覺得想要清楚理解,還是要從TCP報文段首部格式說起

TCP的介紹

傳輸控制協定(TCP,Transmission Control Protocol)是為了在不可靠的網際網路絡上提供可靠的端到端位元組流而專門設計的一個傳輸協定。

TCP報文段首部格式

在這裡插入圖片描述

首部固定部分各欄位意義如下:

源埠和目的埠 : 各佔2個位元組,分別寫入源埠和目的埠。


序號 :佔4位元組。序號範圍是【0,2^32 - 1】,共2^32(即4294967296)個序號。在TCP連線中傳送的位元組流中的每一個位元組都按順序編號,本欄位表示本報文段所傳送資料的第一個位元組的序號
例如,一報文段的序號是201,而接待的資料共有100位元組。這就表明:本報文段的資料的第一個位元組的序號是201,最後一個位元組的序號是300。顯然,下一個報文段(如果還有的話)的資料序號應當從301開始,即下一個報文段的序號欄位值應為401。這個欄位的序號也叫「報文段序號」。


確認號 :佔4位元組,是期望收到對方下一個報文段的第一個資料位元組的序號。
例如,B正確收到了A傳送過來的一個報文段,其序號欄位值是501,而資料長度是200位元組(序號501~700),這表明B正確收到了A傳送的到序號700為止的資料。因此,B期望收到A的下一個資料序號是701,於是B在傳送給A的確認報文段中把確認號置為701。注意,現在確認號不是501,也不是700,而是701。
簡而言之:若確認號為= N,則表明:到序號N-1為止的所有資料都已正確收到。


資料偏移 : 佔4位元,它指出TCP報文段的資料起始處距離TCP報文段的起始處有多遠。這個欄位實際上是指出TCP報文段的首部長度。由於首部中還有長度不確定的選項欄位,因此資料偏移欄位是必要的,但應注意,「資料偏移」的單位是32位元字(即以4位元組的字為計算單位)。由於4位元二進位制數能表示的最大十進位制數位是15(最大的四位二進位制1111),因此資料偏移的最大值是60位元組,這也是TCP首部的最大位元組(即選項長度不能超過40位元組因為有20位元組的固定首部)。


緊急URG: 當URG=1時,表明緊急指標欄位有效。它告訴系統此報文段中有緊急資料,應儘快傳送(相當於高優先順序的資料),而不要按原來的排隊順序來傳送。
例如,我們傳送檔案好好的,突然接收方說我沒辦法接受檔案了,快停止,傳送方收到資訊就會趕快停止,傳送方叫停需要傳送命令,就會進入TCP快取中,因為我們的URG設定為1,就需要儘快傳送,說白了就是允許插隊,不用去排隊

當URG置為1時,傳送應用程序就告訴傳送方的TCP有緊急資料要傳送。於是傳送方TCP就把緊急資料插入到本報文段資料的最前面,而在緊急資料後面的資料仍然是普通資料。這時要與首部中緊急指標(Urgent Pointer)欄位配合使用。


確認ACK(ACKnowledgment): 僅當ACK = 1時確認號欄位才有效,當ACK = 0時確認號無效。TCP規定,在連線建立後所有的傳送的報文段都必須把ACK置為1。


推播 PSH(PuSH) :當兩個應用程序進行互動式的通訊時,有時在一端的應用程序希望在鍵入一個命令後立即就能收到對方的響應。在這種情況下,TCP就可以使用推播(push)操作。這時,傳送方TCP把PSH置為1,並立即建立一個報文段傳送出去。接收方TCP收到PSH=1的報文段,就儘快地(即「推播」向前)交付接收應用程序。而不用再等到整個快取都填滿了後再向上交付。


復位RST(ReSeT) :當RST=1時,表名TCP連線中出現了嚴重錯誤(如由於主機崩潰或其他原因),必須釋放連線,然後再重新建立傳輸連線。RST置為1還用來拒絕一個非法的報文段或拒絕開啟一個連線。


同步SYN(SYNchronization) : 在連線建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連線請求報文段。對方若同意建立連線,則應在響應的報文段中使SYN=1和ACK=1,因此SYN置為1就表示這是一個連線請求或連線接受報文。(後面三次握手的時候具體來看)


終止FIN(FINis):用來釋放一個連線。當FIN=1時,表明此報文段的傳送發的資料已傳送完畢,並要求釋放運輸連線。(後面四次揮手的時候具體來看)


視窗 :佔2位元組。視窗值是【0,2^16-1】之間的整數。視窗指的是傳送本報文段的一方的接受視窗(而不是自己的傳送視窗)。視窗值告訴對方:從本報文段首部中的確認號算起,接收方目前允許對方傳送的資料量(以位元組為單位)。之所以要有這個限制,是因為接收方的資料快取空間是有限的。總之,視窗值作為接收方讓傳送方設定其傳送視窗的依據。

例如,傳送了一個報文段,其確認號是701,視窗欄位是1000.這就是告訴對方:「從701算起,我(即傳送方報文段的一方)的接收快取空間還可接受1000個位元組資料(位元組序號是701~1700),你在給我發資料時,必須考慮到這一點。」

簡而言之視窗欄位明確指出了現在允許對方傳送的資料量。視窗值經常在動態變化。


檢驗和 :佔2位元組。檢驗首部+資料,檢驗時要加上12B偽首部,第四個欄位為6


緊急指標 :佔2位元組。緊急指標僅在URG=1時才有意義,它指出本報文段中的緊急資料的位元組數(緊急資料結束後就是普通資料) 。因此,在緊急指標指出了緊急資料的末尾在報文段中的位置。當所有緊急資料都處理完時,TCP就告訴應用程式恢復到正常操作。值得注意的是,即使視窗為0時也可以傳送緊急資料


選項 (長度可變)最大報文段MSS,視窗擴大,時間戳,選擇確認;


在這裡插入圖片描述

TCP連線管理

TCP連線傳輸三個階段

在這裡插入圖片描述
TCP連線的建立採用客戶伺服器方式(c/s),主動發起連線建立的應用程序叫做客戶,而被動等待連線建立的應用程序叫伺服器

TCP的三次握手

TCP的三次握手

在這裡插入圖片描述
剛開始使用者端和使用者端都處於關閉的CLOSED狀態,先是伺服器端主動監聽某個埠,處於LISTEN狀態

ROUND 1使用者端會隨機初始化序列號 ISN(c)對應上圖的seq=x將序列號置於TCP首部的【序號】欄位中。同時把SYN標誌位置為1,表示SYN報文,接著把第一個SYN報文傳送給伺服器端,表示伺服器發起連線,之後使用者端處於SYN_Send 狀態。

注意該報文不包括應用層資料 並且此時的ACK是為0,因為使用者端此時沒有收到伺服器端發出的報文段因為此時使用者端不知道期待什麼所以確認號是沒意義的 ,前面我們也說過了,只有接受請求報文和確認請求報文SYN才為1


ROUND 2:伺服器收到使用者端的 SYN 報文之後,會以自己的 SYN 報文作為應答,並且也是指定了自己的初始化序列號 ISN(s)對應上圖的seq=y,同時會把使用者端的 ISN + 1 對應上圖的ack=x+1作為 ack的值,表示自己已經收到了使用者端的 SYN,此時伺服器處於 SYN_REVD 的狀態。

注意該報文不包括應用層資料 ,因為我們說過了SYN兩種情況下才為1,分別是連線請求和連線請求的確認,所以我們現在是連線請求的接受SYN就是1,從二次握手以後連線,已經建立好了,就不需要SYN了,接下來的連線SYN都為0,當連線建立以後ACK為1,我們的確認號ack就有效了,之所以ack=x+1,就是因為我們接下來期待的收到的下一個欄位為傳送端之前傳送的X欄位+1


ROUND 3:使用者端收到 SYN 報文之後,會傳送一個 ACK 報文,當然,也是一樣把伺服器的 ISN + 1 作為 ACK 的值,表示已經收到了伺服器端的 SYN 報文,此時使用者端處於 establised 狀態
伺服器收到 ACK 報文之後,也處於 establised 狀態,此時,雙方以建立起了連結。

Ps:
(1)SYN=1表示該報文不攜帶資料,但消耗一個序號 seq=x,seq=x是使用者端的初始化序列號,因為tcp是面向位元組流的
(2)SYN=1 表示該報文不攜帶資料,但消耗一個序號 seq=y,seq=y是伺服器的初始化序列號,ACK=1是一個確認號
ack=x+1,表示伺服器下次接收到的序號希望是x+1。然後伺服器進入到SYN-RCVD等待的狀態
(3)ACK=1是一個確認號,seq=x+1是上一次伺服器迴應的序號要求,ack=y+1表示客戶下一次接收到的序號希望是y+1

tcp通訊需要確保雙方都具有資料收發的能力,得到ACK響應則認為對方具有資料收發的能力,因此雙方都要傳送SYN確保對方具有通訊的能力。第一次握手是使用者端傳送SYN,伺服器端接收,伺服器端得出使用者端的傳送能力和伺服器端的接收能力都正常;第二次握手是伺服器端傳送SYN+ACK,使用者端接收,使用者端得出使用者端傳送接收能力正常,伺服器端傳送接收能力也都正常,但是此時伺服器並不能確認使用者端的接收能力是否正常;第三次握手使用者端傳送ACK,伺服器接收,伺服器端才能得出使用者端傳送接收能力正常,伺服器端自己傳送接收能力也都正常。
在這裡插入圖片描述


大白話來談TCP的三次握手

舉兩個栗子🌰

村裡有個貧困的人叫老許,一直單身沒有物件,這一天好友老王來給他介紹物件,但是老許還在睡覺

在這裡插入圖片描述在這裡插入圖片描述
在這裡插入圖片描述在這裡插入圖片描述

👴 老王:老許!老許!我是老王,你能聽到嗎?
👨‍🦳 老許猛的驚醒一聽是老王的聲音:老王!老王!我是老許,我能聽到你說話,你能聽到我說話嘛!!
👴 老王一聽,嗯,這是老許的聲音:老許!我能聽到,我給你說個事。

「老許你要老婆不要!」
老許連忙穿上衣服,激動的跑出門了。

上面就是簡單的三次握手建立連線然後傳輸資料的過程,是不是很有趣!!


再來個栗子🌰:
我們大家都寫過💌情書,我們要怎麼知道對方的答案就要經歷這些

將小明當作使用者端,小紅當作伺服器端,兩人寫信告白:
第一次握手
小明寫信告訴小紅:我喜歡你很久了,可不可以和我在一起。
第二次握手
小紅收到信以後寫信告訴小明:我知道了,其實我也喜歡你。
此時小紅並不確定小明是否收到了告白信(因為我們的表白信在傳送的時候可能被那些傳信的人,攔截了,你們上學的時候遇到這樣的嘛!哈哈),然後就等待
第三次握手
小明開啟信很開心回信:我知道了,那我們在一起吧。

此時才真正建立戀愛的關係。
這樣你才算和對方完成,男女朋友才經常做的事情,別想太多,就是膩歪膩歪!!!!!


看到這裡不知道大家有啥疑惑沒有,如果沒有我們來看看這個問題

①為什麼是三次握手?不是兩次,四次?

我們學完了可能就會說,因為三次握手才能保證雙方具有接收和傳送的能力,emmmm,這樣說好像是沒毛病,但是比較片面,並沒說出主要的原因

主要原因是防止失效的連線請求報文段被伺服器端接收,從而產生錯誤。
注意:失效的連線請求:若使用者端向伺服器端傳送的連線請求丟失,使用者端等待應答超時後就會再次傳送連線請求,此時,上一個連線請求就是『失效的』。
a. 若建立連線只需兩次握手,使用者端並沒有太大的變化,仍然需要獲得伺服器端的應答後才進入ESTABLISHED狀態,而伺服器端在收到連線請求後就進入ESTABLISHED狀態。
此時如果網路擁塞,使用者端傳送的連線請求遲遲到不了伺服器端,使用者端便超時重發請求,如果伺服器端正確接收並確認應答,雙方便開始通訊,通訊結束後釋放連線。此時,如果那個失效的連線請求抵達了伺服器端,由於只有兩次握手,伺服器端收到請求就會進入ESTABLISHED狀態,等待傳送資料或主動傳送資料。但此時的使用者端早已進入CLOSED狀態,伺服器端將會一直等待下去,這樣浪費伺服器端連線資源。

採用「三次握手」的辦法可以防止上述現象發生 ,例如上述情況,使用者端沒有向伺服器端的確認發出確認,伺服器由於收不到確認,就知道使用者端並沒有要求建立連線。


②三次握手可以攜帶資料嗎?

第一次、第二次握手不可以攜帶資料,而第三次握手是可以攜帶資料的。假設第一次可以攜帶資料,如果有人惡意攻擊伺服器,每次都在第一次握手中的SYN報文放入大量資料,重複傳送大量SYN報文,此時伺服器會花費大量記憶體空間來緩衝這些報文,伺服器就更容易被攻擊了


TCP的四次揮手

在介紹「四次揮手之前先看個例子」

舉個栗子

還是上面的小明和小紅,現在他們兩個處於熱戀狀態

在這裡插入圖片描述
戀愛之後,小明和小紅經常打電話煲電話粥。依舊將小明當作使用者端,小紅當作伺服器端。小明跟小紅說話,
第一次揮手
小明說:我說完了,也不早了,該睡覺了。
第二次揮手
小紅還不想睡還想繼續說:好的,我知道了,我還沒說完。
小紅繼續吧啦吧啦,說完情話之後
第三次揮手
小紅告訴小明:我說完了。
第四次揮手
小明收到後告訴小紅:好的,我知道了,但是小明也不捨得掛電話。等了2MSL之後小明才結束通話了。
如果此時小紅說完,等了2MSL,小明一直不出聲,這個時候就會重新說一次:我說完了。直到收到小明最後的回覆,才結束通話電話。


那麼我們迴歸TCP的"揮手」
在這裡插入圖片描述

在這裡插入圖片描述
ROUND 1:
使用者端打算關閉連線,此時傳送一個TCP首部FIN標誌位被設定為1的報文,也就是FIN報文,之後使用者端進入FIN_WAIT_1狀態
ROUND 2:
伺服器收到該報文以後,就向用戶端傳送ACK應答報文,接著伺服器進入CLOSE_WAIT狀態,這樣使用者端到伺服器這個方向的連線就釋放了–半關閉狀態,此時伺服器不用給予回覆,因為主機已經結束通話了,只需要等到,伺服器告訴自己他也要結束
ROUND 3:
伺服器端發完資料,就會發出連線釋放報文段,主動關閉TCP連線,之所以第二次和第三次的ack是一樣的,是因為使用者端沒有傳送資料,所以ack期待的下一個報文段不變
ROUND 4:
使用者端回送一個確認報文段,在等到時間,再等到時間等待計時器設定的2MSL(最長報文段壽命)後,連線徹底關閉


看到這裡不知道大家有啥疑惑沒有,如果沒有我們來看看這些問題

為什麼我們第一次連線已經釋放了,可是最後還能回送一個報文段那?

這個問題是我在學習的過程中,彈幕上提到的問題,我也有些疑惑其實,斷了連線只是不傳送資料而已,但是對伺服器還是要回復的,在CLOSED狀態之前,都不能算是真正的關閉

為什麼使用者端傳送ACK之後不直接關閉,而要等待一陣子才關閉

這個是面試的高頻考點,這其中的原因就是,要確保伺服器是否已經收到了我們的 ACK 報文,如果沒有收到的話,伺服器會重新發 FIN 報文給使用者端,使用者端再次收到 ACK 報文之後,就知道之前的 ACK 報文丟失了,然後再次傳送 ACK 報文。至於 TIME_WAIT 持續的時間至少是一個報文的來回時間。一般會設定一個計時,如果過了這個計時沒有再次收到 FIN 報文,則代表對方成功就是 ACK 報文,此時處於 CLOSED 狀態

在這裡插入圖片描述

在這裡插入圖片描述

------🎃 歡迎點贊 👍 收藏 ⭐留言 📝-----
<-----希望大家假期🐟🎊🎊🎊🎊🎊----->
<------------🍻2022新年快樂🥂----------->
<----------✨2022大家一起加油✨---------->