計算機網絡tcp協議三次握手四次揮手

TCP的傳輸連接分爲3個階段:連接建立(三次握手)、數據傳送和連接釋放(四次揮手)。TCP傳輸連接的管理就是使傳輸連接的建立和釋放都能正常地進行。


一、TCP的三次握手

準備工作:服務器必須準備好接受外來的連接。這通常通過調用 socket,bindlisten這三個函數來完成。我們稱之爲 被動打開
第一次握手:客戶端通過調用 connect發起 主動打開。客戶端向服務器發出連接請求的TCP報文段,其TCP首部中的同步比特SYN置爲1,並TCP首部中序號seq設置爲x(TCP規定SYN報文段不能攜帶數據,但是要消耗一個序號),表明要轉送數據時初始序列號是x。通常SYN分節不攜帶數據,其所在IP數據報只含有一個IP首部,一個TCP首部。
第二次握手:服務器收到數據報後,從TCP數據報首部的同步比特SYN位爲1就知道這是一個建立連接的請求。服務器如果同意,會發回確認。在確認報文段中把同步比特位SYN設置爲1,確認比特位ACK設置爲1,由於TCP請求報文段中的序號是x,所以服務器在發送確認報文段中的確認號ack是x+1,同時把確認報文段中的序號seq設置爲y,表明服務器發送數據的初始序列號爲y。該報文段也不能攜帶數據(因爲SYN=1,所以不攜帶任何數據)。
第三次握手:客戶端收到服務器端的報文段後,要對服務器端中的SYN進行確認。在確認報文段中把確認比特位ACK設置爲1,然後把確認號ack設置爲y+1,自身的序號seq設置x+1。
注:客戶的初始序列號爲x,服務器的初始序列號爲y,那麼確認報文段中的確認號ack就是所期待的對方要發送的下一個序列號。

客戶端調用connect將激發TCP的三次握手,僅在連接建立成功或者出錯時才返回,上面介紹了建立成功的情況,下面列出了出錯返回可能有的幾種情況。
(1)客戶端發送的建立連接的SYN報文丟失或者服務器回覆的ACK報文丟失。客戶端因爲沒有收到服務器的回覆,會等待6s再發一次,若無響應則等待24s再發一次,總共等75s還未收到響應就返回本錯誤。
(2)服務器回覆的TCP報文中復位標誌RST置位1。表示服務器主機沒有在指定的端口上監聽或接受該連接或服務器程序根本沒有運行。
(3)客戶端發送的SYN報文不可達。還記IP數據報中有一個生存時間(TTL)的標誌嗎?它每進過一個路由器都會減1,當它減到0時還沒到達目的地,會發送一個ICMP錯誤。然後客戶端會和第一種情況一樣每隔一段時間重發一次。

可以把TCP連接時的三次握手換成兩次握手嗎?(假設客戶端主動,服務器端被動)
假如客戶端發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達服務器。也就是說這是一個早已失效的報文段。但服務器端收到此失效的連接請求報文段後,就誤認爲是客戶端再次發出的一個新的連接請求。於是就向客戶端發出確認報文段,同意建立連接。假設不採用「三次握手」,那麼只要服務器端發出確認,新的連接就建立了。由於現在客戶端並沒有發出建立連接的請求,因此不會理會服務器端的確認。經過三次握手,客戶端和服務器都有應有答可以確保TCP正確連接。

二、TCP的四次揮手

數據傳輸完畢後,通信雙方都可以釋放連接。對於首先調用close的一端我們稱該端爲 主動關閉,另外一端執行 被動關閉
第一次揮手:假設客戶端執行 主動關閉,那麼它會向服務器端發出釋放連接的報文段,這個TCP報文段中終止比特FIN置爲1,序號seq設置爲u(假設上一個發的數據序號是u-1)。並停止發送數據。主動關閉TCP連接。等待服務器的確認,這裏需要注意,因爲TCP是全雙工的,所以TCP連接上有兩條數據通路,發送FIN的一端就不能發送數據,也就是關閉了其中一條數據通路,對方還是可以繼續發送數據。
第二次揮手:服務器端收到客戶端的釋放連接的報文段後會執行被動關閉,它要對客戶端的數據報進行確認,服務器端會發送一個確認的數據報,確認比特ACK設置爲1,確認號爲u+1,自身的序號seq爲v(假設上一個發的數據序號是v-1)。這個時候TCP處於半關閉狀態,服務器依然可以向客戶端發送數據(數據的序號爲v+1 ~ w-1),客戶端任要接受。
第三次揮手:服務器端已經沒有要發送給客戶端的數據,那麼服務器端也會調用close關閉套接字,這樣服務器端也會發送一個FIN的TCP報文段,序號是w(假設上一個發的數據序號是w-1)。這個時候服務器端不會再向客戶端發送數據了。
第四次揮手:客戶端接受到這個最終的FIN的釋放連接報文段後必須對報文段進行確認。在確認的報文段中,ACK=1,確認序號ack=w+1,自己的序號seq=u+1(他的上一個序號的數據報就是申請釋放連接的數據報,序號是seq=u)。

爲什麼TCP握手是三次,揮手卻是四次?(假設客戶端主動,服務器端被動)
在TCP三次握手中,服務器端的SYN和ACK是放在一個TCP報文段中向客戶端發送的,而在斷開連接的過程中,服務器端向客戶單端發送的ACK和FIN是是分別在兩個不同的TCP報文段中。這是因爲在服務器端接收到客戶端的FIN後,服務器端可能還有數據要傳輸,所以先發送ACK,服務器端把數據發完之後就可以發送FIN斷開連接了。