TCP創建鏈接和釋放鏈接過程

在談及TCP創建鏈接和釋放鏈接過程,先來簡單認識一下TCP報文段首部格式的的幾個名詞(這裏只是簡單說明,具體請查看相關教程)服務器

    序列號seq (Sequence Number) 佔4個字節,用來標記數據段的順序,TCP把鏈接中發送的全部數據字節都編上一個序號,第一個字節的編號由本地隨機產生;給字節編上序號後,就給每個報文段指派一個序號;序列號seq就是這個報文段中的第一個字節的數據編號。
    確認號ack (Acknowledgement Number) 佔4個字節,期待收到對方下一個報文段的第一個數據字節的序號;序列號表示報文段攜帶數據的第一個字節的編號;而確認號指的是指望接收到下一個字節的編號;所以當前報文段最後一個字節的編號+1即爲確認號。
    確認ACK:佔1位,僅當ACK=1時,確認號字段纔有效。ACK=0時,確認號無效
    同步SYN:鏈接創建時用於同步序號。當SYN=1,ACK=0時表示:這是一個鏈接請求報文段。若贊成鏈接,則在響應報文段中使得SYN=1,ACK=1。所以,SYN=1表示這是一個鏈接請求,或鏈接接受報文。SYN這個標誌位只有在TCP建產鏈接時纔會被置1,握手完成後SYN標誌位被置0。
    終止FIN(Finish)用來釋放一個鏈接。FIN=1表示:此報文段的發送方的數據已經發送完畢,並要求釋放運輸鏈接網絡

    PS:ACK、SYN和FIN這些大寫的單詞表示標誌位,其值要麼是1,要麼是0;ack、seq小寫的單詞表示序號。併發

1、TCP創建鏈接三次握手spa

(1)、三次握手的過程.net

   1)主機A向主機B發送TCP鏈接請求數據包,其中包含主機A的初始序列號seq(A)=x。(其中報文中同步標誌位SYN=1,ACK=0,表示這是一個TCP鏈接請求數據報文;序號seq=x,代表傳輸數據時的第一個數據字節的序號是x)blog


   2)主機B收到請求後,會發回鏈接確認數據包。(其中確認報文段中,標識位SYN=1,ACK=1,表示這是一個TCP鏈接響應數據報文,並含主機B的初始序列號seq(B)=y,以及主機B對主機A初始序列號的確認號ack(B)=seq(A)+1=x+1)教程


   3)第三次,主機A收到主機B的確認報文後,還需做出確認,即發送一個序列號seq(A)=x+1;確認號爲ack(A)=y+1的報文;進程

(2)爲何須要第三次握手?資源

     還要再發送一次確認是爲了,防止已失效的鏈接請求報文段忽然又傳到了B,於是產生錯誤。
     已失效的報文段:正常狀況下:A發出鏈接請求,但由於丟失了,故而不能收到B的確認。因而A從新發出請求,而後收到確認,創建鏈接,數據傳輸完畢後,釋放鏈接,A發了2個,一個丟掉,一個到達,沒有「已失效的報文段」
     可是,某種狀況下,A的第一個在某個節點滯留了,延誤到達,原本這是一個早已失效的報文段,可是在A發送第二個,而且獲得B的迴應,創建了鏈接之後,這個報文段居然到達了,因而B就認爲,A又發送了一個新的請求,因而發送確認報文段,贊成創建鏈接,倘若沒有三次的握手,那麼這個鏈接就創建起來了(有一個請求和一個迴應),此時,A收到B的確認,但A知道本身並無發送創建鏈接的請求,由於不會理睬B的這個確認,因而呢,A也不會發送任何數據,而B呢卻覺得新的鏈接創建了起來,一直等待A發送數據給本身,此時B的資源就被白白浪費了。可是採用三次握手的話,A就不發送確認,那麼B因爲收不到確認,也就知道並無要求創建鏈接。
同步

     簡而言之:第三次握手,主機A發送一次確認是爲了防止:若是客戶端遲遲沒有收到服務器返回的確認報文,這時他會放棄鏈接,從新啓動一條鏈接請求;但問題是:服務器不知客戶端沒收到,因此他會收到兩個鏈接請求,白白浪費了一條鏈接開銷。

 

2、TCP釋放鏈接四次握手

(1)四次握手過程

  假設主機A爲客戶端,主機B爲服務器,其釋放TCP鏈接的過程以下:

    1) 關閉客戶端到服務器的鏈接:首先客戶端A發送一個FIN,用來關閉客戶到服務器的數據傳送,而後等待服務器的確認。其中終止標誌位FIN=1,序列號seq=u

   2) 服務器收到這個FIN,它發回一個ACK,確認號ack爲收到的序號加1。
   3) 關閉服務器到客戶端的鏈接:也是發送一個FIN給客戶端。
   4) 客戶段收到FIN後,併發回一個ACK報文確認,並將確認序號seq設置爲收到序號加1。

     首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。

     主機A發送FIN後,進入終止等待狀態, 服務器B收到主機A鏈接釋放報文段後,就當即給主機A發送確認,而後服務器B就進入close-wait狀態,此時TCP服務器進程就通知高層應用進程,於是從A到B的鏈接就釋放了。此時是「半關閉」狀態。即A不能夠發送給B,可是B能夠發送給A。
  此時,若B沒有數據報要發送給A了,其應用進程就通知TCP釋放鏈接,而後發送給A鏈接釋放報文段,並等待確認。A發送確認後,進入time-wait,注意,此時TCP鏈接尚未釋放掉,而後通過時間等待計時器設置的2MSL後,A才進入到close狀態。


(2)爲何要等待2MSL呢?
    MSL即Maximum Segment Lifetime,也就是最大報文生存時間,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。引用《TCP/IP詳解》中的話:「它(MSL)是任何報文段被丟棄前在網絡內的最長時間」。RFC 793中規定MSL爲2分鐘,實際應用中經常使用的是30秒,1分鐘和2分鐘等。

    TCP的TIME_WAIT狀態須要等待2MSL,當TCP的一端發起主動關閉,在發出最後一個ACK包後,即第3次握手完成後發送了第四次握手的ACK包後就進入了TIME_WAIT狀態,必須在此狀態上停留兩倍的MSL時間,等待2MSL時間主要目的是怕最後一個ACK包對方沒收到,那麼對方在超時後將重發第三次握手的FIN包,主動關閉端接到重發的FIN包後能夠再發一個ACK應答包。在TIME_WAIT狀態時兩端的端口不能使用,要等到2MSL時間結束纔可繼續使用。當鏈接處於2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中能夠經過設置SO_REUSEADDR選項達到沒必要等待2MSL時間結束再使用此端口。

    歸納緣由以下:

    ①、爲了保證A發送的最後一個ACK報文段可以到達B。即最後這個確認報文段頗有可能丟失,那麼B會超時重傳,而後A再一次確認,同時啓動2MSL計時器,如此下去。若是沒有等待時間,發送完確認報文段就當即釋放鏈接的話,B就沒法重傳了(鏈接已被釋放,任何數據都不能出傳了),於是也就收不到確認,就沒法按照步驟進入CLOSE狀態,即必須收到確認才能close。
    ②、防止「已失效的鏈接請求報文段」出如今鏈接中。通過2MSL,那些在這個鏈接持續的時間內,產生的全部報文段就能夠都從網絡中消失。即在這個鏈接釋放的過程當中會有一些無效的報文段滯留在樓閣結點,可是呢,通過2MSL這些無效報文段就確定能夠發送到目的地,不會滯留在網絡中。這樣的話,在下一個鏈接中就不會出現上一個鏈接遺留下來的請求報文段了。
能夠看出:B結束TCP鏈接的時間比A早一點,由於B收到確認就斷開鏈接了,而A還得等待2MSL.

 

(3)爲何TCP釋放鏈接須要四次?

      TCP創建鏈接要進行三次握手,而斷開鏈接要進行四次。這是因爲TCP的半關閉形成的。由於TCP鏈接是全雙工的(即數據可在兩個方向上同時傳遞)因此進行關閉時每一個方向上都要單獨進行關閉。這個單方向的關閉就叫半關閉。當一方完成它的數據發送任務,就發送一個FIN來向另外一方通告將要終止這個方向的鏈接。

     注意:

     1)發送了FIN只是表示這端不能繼續發送數據(應用層不能再調用send發送),可是還能夠接收數據。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP鏈接在收到一個FIN後仍能發送數據,好比:如主機A收到主機B的FIN斷開TCP鏈接請求,只是表示主機B已經發送完數據,主機A收到FIN後做出應答,並終止這個方向的數據傳輸,此時處於半關閉狀態。可是主機A仍然能夠發送數據的,只有當主機A發送完數據併發送FIN給主機B時,主機B才中止這個方向的數據傳輸,並關閉TCP鏈接。

     2)在不少時候,TCP鏈接的斷開都會由TCP層自動進行,例如你CTRL+C終止你的程序,TCP鏈接依然會正常關閉,你能夠寫代碼試試。

https://img-blog.csdn.net/20160809153521584

相關文章
相關標籤/搜索