1. 程式人生 > >TCP三次握手和四次揮手.md

TCP三次握手和四次揮手.md

TCP三次握手和四次揮手

1 三次握手

1.1 基礎知識

  • SYN(SYNchronization):同步序號,用來建立連線。 SYN標誌位和ACK標誌位搭配使用,當SYN=1,ACK=0,表示連線請求;當SYN=1,ACK=1,表示連線被響應的時候;這個標誌的資料包經常被用來進行埠掃描。
  • ACK(ACKnowledgment):確認號,用於確認連線是否有效。 僅當ACK=1時確認號欄位有效,當ACK=0時是無效的。TCP規定在連線建立後所有傳送的報文段都必須把ACK置為1。
  • ACKNum(Acknowledgment Number):所期望收到的下一個序列號。 32位確認序列號包含傳送確認的一端所期望收到的下一個序號,因此,確認序號應當是上次已成功收到資料位元組序號加1。不過,只有當標誌位中的ACK標誌(下面介紹)為1時該確認序列號的欄位才有效。主要用來解決不丟包的問題;
  • seq(Sequence Number):序列號。
  • FIN(finish):表示終結連線。 當 FIN = 1 時,表明此報文段的傳送方的資料已經發送完畢,並要求釋放連線。

1.2 三次握手過程

  • 第一次握手(SYN=1,ACK=0,seq=x) 客戶端傳送一個TCP的資料包(SYN=1,ACK=0)指明客戶端打算連線伺服器的埠,以及初始序號 X,儲存在包頭的序列號(Sequence Number)欄位裡。
  • 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1) 伺服器發回確認包(ACK)應答。即 SYN 標誌位和 ACK 標誌位均為1。伺服器端選擇自己 seq序列號,放到 Seq 域裡,同時將確認序號(ACKNum)設定為客戶的 seq加1,即X+1。 傳送完畢後,伺服器端進入 SYN_RCVD
    狀態。
  • 第三次握手(ACK=1,ACKnum=y+1) 客戶端再次傳送確認包(ACK),SYN 標誌位為0,ACK 標誌位為1,並且把伺服器發來 ACK 的序號欄位+1,放在確定欄位中傳送給對方,並且在資料段放寫seq的+1傳送完畢後,客戶端進入 ESTABLISHED 狀態,當伺服器端接收到這個包時,也進入 ESTABLISHED 狀態,TCP 握手結束。

完成了三次握手,客戶端和伺服器端就可以開始傳送資料。

1.3 現實場景

客戶端:“你好,在家不,有你的快遞?”

服務端:“在的,送上來吧”

客戶端:“好,這就給你送上來”

2 四次揮手

為了避免伺服器與客戶端雙方的資源佔用和損耗,當雙方沒有請求或響應傳遞時,任意一方都可以發起關閉請求。與建立TCP連線的3次握手類似,關閉TCP連線,需要4次握手

TCP 的連線的拆除需要傳送四個包,因此稱為四次揮手(Four-way handshake),也叫做改進的三次握手。客戶端或伺服器均可主動發起揮手動作,在 socket 程式設計中,任何一方執行 close() 操作即可產生揮手操作。

2.1 基礎知識

  • FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連線,向對方傳送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。(主動方)
  • FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連線,也即有一方要求close連線,但另外還告訴對方,我暫時還有點資料需要傳送給你(ACK資訊),稍後再關閉連線。(主動方)
  • CLOSE_WAIT:這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後傳送FIN報文給自己,你係統毫無疑問地會迴應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有資料傳送給對方,如果沒有的話,那麼你也就可以 close這個SOCKET,傳送FIN報文給對方,也即關閉連線。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連線。(被動方)
  • LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在傳送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。(被動方)
  • TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)
  • CLOSED: 表示連線中斷。

2.2 四次揮手過程

  • 第一次揮手(FIN=1,seq=x) 假設客戶端想要關閉連線,客戶端傳送一個 FIN 標誌位置為1的包,表示自己已經沒有資料可以傳送了,但是仍然可以接受資料。傳送完畢後,客戶端進入 FIN_WAIT_1 狀態。
  • 第二次揮手(ACK=1,ACKnum=x+1) 伺服器端確認客戶端的 FIN 包,傳送一個確認包,表明自己接受到了客戶端關閉連線的請求,但還沒有準備好關閉連線。傳送完畢後,伺服器端進入 CLOSE_WAIT 狀態,客戶端接收到這個確認包之後,進入 FIN_WAIT_2 狀態,等待伺服器端關閉連線。
  • 第三次揮手(FIN=1,seq=y) 伺服器端準備好關閉連線時,向客戶端傳送結束連線請求,FIN 置為1。傳送完畢後,伺服器端進入 LAST_ACK 狀態,等待來自客戶端的最後一個ACK。
  • 第四次揮手(ACK=1,ACKnum=y+1) 客戶端接收到來自伺服器端的關閉請求,傳送一個確認包,並進入 TIME_WAIT狀態,等待可能出現的要求重傳的 ACK 包。伺服器端接收到這個確認包之後,關閉連線,進入 CLOSED 狀態。客戶端等待了某個固定時間(兩個最大段生命週期,2MSL,2 Maximum Segment Lifetime)之後,沒有收到伺服器端的 ACK ,認為伺服器端已經正常關閉連線,於是自己也關閉連線,進入 CLOSED 狀態。

2.3 現實場景

客戶端:“兄弟,我這邊沒資料要傳了,咱關閉連線吧。”

服務端:“收到,我看看我這邊有木有資料了。”

服務端:“兄弟,我這邊也沒資料要傳你了,咱可以關閉連線了。”

客戶端:“好嘞。”