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

TCP三次握手與四次揮手

計算機網路中TCP的三次握手與四次揮手一直都不是很清楚,今天認真的學習了一下,在此記錄下來:

三次握手:

這裡A代表TCP客戶端程式(Client),B代表TCP伺服器程式,最初兩者都是處於CLOAE(關閉)狀態。現在A先開啟連線,B被動開啟連線 ,B的TCP伺服器程序先建立傳輸控制塊TCB,準備接收客戶端程序的連線,並處於LISTEN(收聽狀態):

(1)第一次握手:A的TCP客戶程序也先建立傳輸控制塊TCB,然後A首次傳送同步位(SYN=1),序列號隨機數字x(seq=x)的報文段,SYN報文段不攜帶資料,但是要消耗一個序列號。同時A進入SYN-SENT(同步傳送)狀態;

(2)第二次握手:B接收到A的報文段請求後,如果同意連線,著發出確認:SYN和ACK都設定為1,序列號選擇另一個隨機數seq=y,確認號為ack=x+1。此報文也是不能攜帶資料,同樣消耗了一個序號。這時B處於SYN-RCVD(同步接收狀態)

(3)第三次握手:A收到收到B的確認後,還要給B傳送確認。確認報文段的ACK=1,確認號ack=y+1,自己的序號seq=x+1,ACK報文段可以攜帶資料,如果不攜帶則不消耗序號。這時A和B的TCP連線已經建立,A進入ESTABLISHED(已建立連線)狀態。

B收到A的確認後也進入ESTABLISHED(已建立連線)狀態。

問題:

為什麼A還要傳送一次確認?

為了防止已失效的報文又傳到了B。考慮這樣一種情況:假設A傳送了連線請求報文,丟失了沒有收到確認。再次傳送一個請求,收到確認並建立了TCP連線,資料傳輸結束後又釋放了TCP連線。但是第一次傳送的那個請求是在某個網路結點長期滯留了,但是在連線釋放以後的某個結點到達了B,B誤認為是A的一次新的連線請求,所以同意連線。並向A傳送確認,但是A並沒有傳送建立連線請求,所以不會理睬B,B卻一直等待A的資料,白白浪費了資源。

三次揮手:

TCP釋放過程要複雜一些,現在A和B都處在建立連線的狀態:

(1)第一次揮手:A首先向B發出釋放報文,並停止傳送資料,釋放報文的首部控制位FIN置1,序號seq=u(等於前面已經傳送過來的資料的最後一個位元組的序號加1).這時A進入FIN-WAIT-1(終止等待1)狀態,等待B的確認。

(2)第二次揮手:B收到釋放報文段後傳送確認,ACK=1,確認號ack=u+1,序號seq=v(等於前面已經傳送過來的資料的最後一個位元組的序號加1),然後B進入CLOSEWAIT(關閉)狀態。A到B的這個方向的連線就釋放了。這時TCP處於半關閉狀態,A已經沒有資料要傳送了,但是如果B還有資料要傳送,A仍然要接收。

(3)第三次揮手:A收到B的確認後就處於FIN-WAIT-2(終止等待2)狀態,等待B發出釋放報文。當B的資料傳輸完了,就像A傳送釋放報文:FIN=1,ACK=1,seq=w(等於前面已經傳送過來的資料的最後一個位元組的序號加1),B還必須重複上次已經發送過的確認號:ack=u+1.這時A就進入到了LAST-ACK(最後確認)狀態。等待A的確認。

(4)第四次揮手:A收到B的報文後,必須再發送確認:ACK=1,seq=u+1(FIN報文要消耗一個序號),ack=w+1。然後進入到TIME-WAIT(時間等待)狀態。此時連線還沒有被釋放掉,還需要經過一個時間等待計時器(TIME-WAIT timer)設定成兩個最長報文壽命及2MSL(Maximum Segment Lifetime),時間到了A進入CLOSED狀態。

B收到確認後也進入CLOSED狀態。

問題:

連線的時候是三次握手,為什麼釋放的時候需要四次揮手

以為連線的時候同步SYN和確認ACK可以同時傳送。但是揮手時,因為B有可能資料沒有傳輸完,終止FIN和ACK不能同時傳送。這樣就多出了一次揮手。

參考文章: