golang:三次握手四次揮手總結


TCP的三次握手

所謂三次握手 Three-Way Handshake 是指建立一個TCP連接時,需要客戶端和服務端總共發送3個包以確認連接的建立。好比兩個人在打電話:

當連接被建立或被終止,交換的報文段只包含TCP頭部,而沒有數據。

tcp報文頭部結構

  • 序號:seq序號,占32位,用來標識從TCP源端向目的端發送的字節流,發起方發送數據時對此進行標記。
  • 確認序號:ack序號,占32位,只有ACK標志位為1時,確認序號字段才有效,確認方ack=發起方seq+1,兩端配對。
  • 標志位
    • ACK:確認序號有效。
    • FIN:釋放一個連接。
    • RST:重置連接。
    • SYN:發起一個新連接。
    • PSH:接收方應該盡快將這個報文交給應用層。
    • URG:緊急指針(urgent pointer)有效。

    第一次握手:客戶端要向服務端發起連接請求,首先客戶端隨機生成一個起始序列號ISN(比如是100),那客戶端向服務端發送的報文段包含SYN標志位(也就是SYN=1),序列號seq=100。

    第二次握手:服務端收到客戶端發過來的報文后,發現SYN=1,知道這是一個連接請求,於是將客戶端的起始序列號100存起來,並且隨機生成一個服務端的起始序列號(比如是300)。然后給客戶端回復一段報文,回復報文包含SYN和ACK標志(也就是SYN=1,ACK=1)、序列號seq=300、確認號ack=101(客戶端發過來的序列號+1)。

    第三次握手:客戶端收到服務端的回復后發現ACK=1並且ack=101,於是知道服務端已經收到了序列號為100的那段報文;同時發現SYN=1,知道了服務端同意了這次連接,於是就將服務端的序列號300給存下來。然后客戶端再回復一段報文給服務端,報文包含ACK標志位(ACK=1)、ack=301(服務端序列號+1)、seq=101(第一次握手時發送報文是占據一個序列號的,所以這次seq就從101開始,需要注意的是不攜帶數據的ACK報文是不占據序列號的,所以后面第一次正式發送數據時seq還是101)。當服務端收到報文后發現ACK=1並且ack=301,就知道客戶端收到序列號為300的報文了,就這樣客戶端和服務端通過TCP建立了連接。

四次揮手

    比如客戶端初始化的序列號ISA=100,服務端初始化的序列號ISA=300。TCP連接成功后客戶端總共發送了1000個字節的數據,服務端在客戶端發FIN報文前總共回復了2000個字節的數據。

    第一次揮手:當客戶端的數據都傳輸完成后,客戶端向服務端發出連接釋放報文(當然數據沒發完時也可以發送連接釋放報文並停止發送數據),釋放連接報文包含FIN標志位(FIN=1)、序列號seq=1101(100+1+1000,其中的1是建立連接時占的一個序列號)。需要注意的是客戶端發出FIN報文段后只是不能發數據了,但是還可以正常收數據;另外FIN報文段即使不攜帶數據也要占據一個序列號。

    第二次揮手:服務端收到客戶端發的FIN報文后給客戶端回復確認報文,確認報文包含ACK標志位(ACK=1)、確認號ack=1102(客戶端FIN報文序列號1101+1)、序列號seq=2300(300+2000)。此時服務端處於關閉等待狀態,而不是立馬給客戶端發FIN報文,這個狀態還要持續一段時間,因為服務端可能還有數據沒發完。

    第三次揮手:服務端將最后數據(比如50個字節)發送完畢后就向客戶端發出連接釋放報文,報文包含FIN和ACK標志位(FIN=1,ACK=1)、確認號和第二次揮手一樣ack=1102、序列號seq=2350(2300+50)。

    第四次揮手:客戶端收到服務端發的FIN報文后,向服務端發出確認報文,確認報文包含ACK標志位(ACK=1)、確認號ack=2351、序列號seq=1102。注意客戶端發出確認報文后不是立馬釋放TCP連接,而是要經過2MSL(最長報文段壽命的2倍時長)后才釋放TCP連接。而服務端一旦收到客戶端發出的確認報文就會立馬釋放TCP連接,所以服務端結束TCP連接的時間要比客戶端早一些。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM