大白話告訴你 TCP 爲什麼需要三次握手四次揮手 三次握手 四次揮手 疑問 總結

關於 TCP 的三次握手和四次揮手相比大家早就爛熟於心了,畢竟這也是一個高頻的面試題,但是很多小夥伴只是照本宣科,並沒有真正的理解其中的原理,這篇文章,阿粉用通俗易懂的大白話帶你們重新熟悉一下,已經掌握的小夥伴可以在回味一下,沒有掌握的小夥伴剛好可以查漏補缺。

三次握手

再解釋三次握手之前我們先從生活中想一個場景,假如你現在需要給領導打個電話彙報一下工作,爲了保證雙方能正常交流,那麼在電話接通的那一刻想象一下會不會是這樣的場景。

我們:領導好,我是 xx,可以聽到我說話嗎?有個工作需要向您彙報下。

領導:嗯,可以的,能聽到我說話吧。

我們:可以。

我們:.....(彙報工作)。

通過上面的場景我們可以看出,其實跟 TCP 的三次握手是一個意思,只不過在我們日常生活中並不是每次都這麼嚴謹,但是 TCP 不一樣,TCP 是通過程序實現的,可靠的,面向連接的協議。而且程序是嚴謹的,每一次的建立連接都會進行這樣的步驟。放一張經典的 TCP 三次握手圖。

我們先用大白話解釋一下爲什麼需要三次握手,首先我們要知道建立連接的目的是什麼,我們是爲了可靠的傳輸數據。那既然是可靠的傳輸數據,我們必須保證客戶端和服務端都能正常的發送和接收數據,如果某一方不能正常的發送或者接收數據,那整個數據的傳輸就不能成功也就不可靠了。知道這個我們看下,爲什麼會需要三次握手,而不是兩次握手。

  1. 剛開始客戶端和服務端都是處於關閉的狀態,而且服務器 B 端一直處於監聽的狀態,時刻監聽是否有建立連接的請求;
  2. 當有客戶端需要建立連接的時候就會發送一個確定連接的報文,此報文是同步報文SYN = 1,並且會生成一個隨機的序號 seq = x,這是第一次握手;
  3. 當服務端接收到請求連接報文的時候,會發送一個同步報文確認報文,此報文 SYN = 1,並且 ACK = 1,同時服務端也會隨機生成一個 seq = y,並將 ack 設置成 x + 1,回傳給客戶端,這是第二次握手;
  4. 當客戶端接收到服務端的 ACK 報文後,會回覆一個 ACK 確認報文,用於確認確認報文已經收到,此報文 ACK = 1,seq = x + 1, ack = y + 1,這是第三次握手;

這裏有個點說明一下:大寫的 ACK 表示報文的類型是確認報文,小寫的 ack 是報文裏面的確認號,這個確認號是上一次握手對方的 seq 值加 1 得到。

上面是整個三次握手的過程,現在我們分析一下爲什麼三次握手可以可靠的確定客戶端和服務端都能支持的發送和接收數據。

第一次握手:第一次握手是客戶端發送同步報文到服務端,這個時候客戶端是知道自己具備發送數據的能力的,但是不知道服務端是否有接收和發送數據的能力;

第二次握手:當服務端接收到同步報文後,回覆確認同步報文,此時服務端是知道客戶端具有發送報文的能力,並且知道自己具有接收和發送數據的能力,但是並不知道客戶端是否有接收數據的能力;

第三次握手:當客戶端收到服務端的確認報文後,知道服務端具備接收和發送數據的能力,但是此時服務端並不知道自己具有接收的能力,所以還需要發送一個確認報文,告知服務端自己是具有接收能力的。

當整個三次握手結束過後,客戶端和服務端都知道自己和對方具備發送和接收數據的能力,隨後整個連接建立就完成了,可以進行後續數據的傳輸了。

看到這裏,如果大家理解了就會知道很明顯,兩次握手是不行的,因爲服務端並不知道客戶端是具備接收數據的能力,所以就不能成爲面向連接的可靠的傳輸協議。就像我們上面提到的打電話的例子,也是爲了雙方能夠正常的進行交流,只不過我們現實生活中不會那麼嚴謹,並不是每次都這樣,但是程序是不一樣的。

四次揮手

三次握手是爲了建立可靠的數據傳輸通道,四次揮手則是爲了保證等數據完成的被接收完再關閉連接。既然提到需要保證數據完整的傳輸完,那就需要保證雙方都達到關閉連接的條件才能斷開。

從上圖中我們可以看到,

  1. 客戶端發起 FIN 斷開連接的報文,攜帶隨機生成的 seq 值 u,發送給服務端,並且自己處於 FIN-WSIT 狀態,這是第一次揮手;
  2. 服務端接收到 FIN 報文後,回覆一個確認報文,其中 ACK = 1,隨機生成一個 seq,以及 ack = u + 1,這是第二次揮手;
  3. 當服務端數據發送完了過後,再發送一個 FIN 報文給客戶端,通知客戶端,服務端準備關閉連接了,此報文 FIN = 1,ACK = 1,ack = u + 1,seq = w,這是第三次揮手;
  4. 當客戶端收到 FIN 確認報文時再發送一個FIN 的確認報文,其中 ACK = 1,seq = u + 1,ack = w + 1,並進入 TIME-WAIT 狀態,當等待 2MSL 後關閉連接,這是第四次揮手。

第一次揮手客戶端發起關閉連接的請求給服務端;

第二次揮手:服務端收到關閉請求的時候可能這個時候數據還沒發送完,所以服務端會先回復一個確認報文,表示自己知道客戶端想要關閉連接了,但是因爲數據還沒傳輸完,所以還需要等待;

第三次揮手:當數據傳輸完了,服務端會主動發送一個 FIN 報文,告訴客戶端,表示數據已經發送完了,服務端這邊準備關閉連接了。

第四次揮手:當客戶端收到服務端的 FIN 報文過後,會回覆一個 ACK 報文,告訴服務端自己知道了,再等待一會就關閉連接。

疑問

  1. 爲什麼握手要三次,揮手卻要四次呢?那是因爲握手的時候並沒有數據傳輸,所以服務端的 SYN 和 ACK 報文可以一起發送,但是揮手的時候有數據在傳輸,所以 ACK 和 FIN 報文不能同時發送,需要分兩步,所以會比握手多一步。
  2. 爲什麼客戶端在第四次揮手後還會等待 2MSL?等待 2MSL 是因爲保證服務端接收到了 ACK 報文,因爲網絡是複雜了,很有可能 ACK 報文丟失了,如果服務端沒接收到 ACK 報文的話,會重新發送 FIN 報文,只有當客戶端等待了 2MSL 都沒有收到重發的 FIN 報文時就表示服務端是正常收到了 ACK 報文,那麼這個時候客戶端就可以關閉了。

總結

TCP 協議是面向連接的可靠的傳輸層協議,它的擁塞控制,失敗重傳等機制在互聯網數據傳輸中是不可或缺的。當下互聯網行業中,基於 TCP 實現的程序數不勝數。對於我們程序員來說,很多時候如果不是參與底層項目的話,很少有機會會主動編寫 TCP 相關的代碼,但是理解 TCP 的實現原理,對我們來說是很有幫助的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章