TCP的四次揮手過程

看热闹的咸鱼發表於2024-05-12

TCP連線是雙向傳輸的對等的模式(全雙工模式),就是說雙方都可以同時向對方傳送或接收資料。
而斷開的時候,也是雙方都可以主動斷開,此時需要經過四次揮手的過程,流程如下圖所示:
TCP四次揮手

  1. 主動方傳送FIN包給被動方,主動方狀態變成FIN_WAIT_1,等待被動方的確認。此時主動方不能再傳送資料。
  2. 被動方收到FIN之後,返回ACK包給主動方,確認自己收到這個包,被動方狀態變成CLOSE_WAIT,等待關閉連線(等待快取資料都傳送過去)
  3. 主動方收到ACK之後,狀態變成FIN_WAIT_2,等待被動方的FIN包。
  4. 被動方將緩衝區剩餘的資料傳送給主動方。
  5. 被動方傳送FIN給主動方,被動方狀態變成LAST_ACK狀態。
  6. 主動方收到FIN之後,返回ACK包給被動方,主動方變成TIME_WAIT狀態。
  7. 被動方收到ACK確認後,變成CLOSE狀態。
  8. 主動方在經過2MSL時間之後,變成CLOSE狀態。

MSL(Maximum Segment Lifetime)指報文最大生存時間,它是任何報文在網路上存在的最長時間,超過這個時間報文將被丟棄。

為什麼握手需要三次,而揮手需要四次?

因為 TCP連線是全雙工模式,一方斷開連線,另一方還是可以繼續傳送資料,所以無法像三次握手一樣,將 FINACK合併到一起,而是需要等待被動方處理完所有資料,不再有資料傳送時,才會傳送 FIN,來關閉被動方的連線。

為什麼需要 TIME_WAIT狀態?

需要 TIME_WAIT 狀態,主要是兩個原因:

  1. 防止歷史連線中的資料,被後面相同四元組的連線錯誤的接收:
    在連線關閉過程中,可能會存在一些延遲的資料包在網路中,這些資料包可能在連線關閉後到達目的地。TIME_WAIT 狀態的存在可以確保在這段時間內不會接收到與當前連線相關的舊資料包,防止這些資料包造成連線的混亂。
  2. 保證「被動關閉連線」的一方,能被正確的關閉:
    如果主動方收到 FIN,發出 ACK之後,直接進入 CLOSE狀態,那麼當這個 ACK丟失時,被動方收不到 ACK則會重發一個 FIN,但此時主動方已經是 CLOSE狀態,無法再給被動方傳送 ACK了。

如果兩端同時關閉,會出現什麼情況?

前面說過,TCP連線雙方都可以主動斷開,那如果兩邊同時斷開,會怎樣呢?
TCP同時斷開

從上圖可以看到,一方發出FIN,進入FIN_WAIT_1狀態,原本期待收到ACK,但此時收到了FIN,則會變成CLOSING狀態,等到收到ACK時,再進入TIME_WAIT狀態,同樣要經過2MSL時間變成CLOSE狀態。

參考資料

  • TCP連線斷開 - 小林coding

相關文章