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

TCP的三次握手

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

當鏈接被創建或被終止,交換的報文段只包含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。code

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

    第三次握手:客戶端收到服務端的回覆後發現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個字節的數據。im

    第一次揮手:當客戶端的數據都傳輸完成後,客戶端向服務端發出鏈接釋放報文(固然數據沒發完時也能夠發送鏈接釋放報文並中止發送數據),釋放鏈接報文包含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=110二、序列號seq=2350(2300+50)。img

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

相關文章
相關標籤/搜索