TCP創建鏈接的過程叫作握手,握手須要在客戶和服務器之間交換三個 TCP 報文段。html
最初,客戶端和服務器的 TCP 進程都處於 CLOSED (關閉) 狀態。B 的 TCP 服務器進程先建立 傳輸控制塊 TCB ,準備接受客戶進程的鏈接請求。而後服務器進程處於 LISTEN (收聽) 狀態,等待客戶的鏈接請求。A 的 TCP 客戶進程也是首先建立 傳輸控制塊 TCB 。
服務器
第一次握手 : 客戶端打算創建鏈接時,向服務器發出鏈接請求報文段,此時首部中的同步位 SYN = 1 ,同時選擇一個初始須要 seq = x 。 TCP 規定,SYN = 1 的報文段 不能攜帶數據,但要消耗掉一個序號。這時,TCP 客戶進程進入 SYN-SENT (同步已發送)狀態。
網絡
第二次握手:服務器收到鏈接請求報文段後,若是贊成創建鏈接,則向客戶端發送確認。在確認報文段中應把 SYN 位 和 ACK 位 都置 1 ,確認號是 ack = x + 1,同時也爲本身選擇一個初始序號 seq = y。(這個報文段也不能攜帶數據,但一樣要消耗掉一個序號。)這時 TCP 服務器進程進入 SYN-RCVD (同步收到) 狀態。
計算機網絡
第三次握手:客戶端收到服務器的確認後,還要向服務器給出確認。確認報文段的 ACK 置爲 1 ,確認號 ack = y + 1,而本身的序號 seq = x + 1 。這時, TCP 鏈接已經創建,客戶端進入 ESTABLISHED (已創建鏈接) 狀態。當 服務器 收到 客戶端 的確認後,也進入 ESTABLISHED (已創建鏈接) 狀態。3d
經過這樣的三次握手,客戶端與服務器端創建可靠的雙工的鏈接,開始傳送數據。三次握手的主要目的是保證鏈接是雙工的,可靠更可能是經過重傳機制來保證的。
cdn
主要是爲了防止已失效的鏈接請求報文段忽然又傳到了 服務器,於是產生錯誤。 htm
現假定出現一種異常狀況,即 客戶端 發出的第一個鏈接請求報文段並無丟失,而是在某些網絡結點長時間滯留了,以至延誤到鏈接釋放之後的某個時間纔到達 服務器。原本這是一個早已失效的報文段。但 服務器 收到此失效的鏈接請求報文段後,就誤認爲是 客戶端 又發出一次新的鏈接請求。因而就向 客戶端 發出確認報文段,贊成創建鏈接。假定不採用報文握手,那麼只要 服務器發出確認,新的鏈接就創建了。因爲如今 客戶端 並無發出創建鏈接的請求,所以不會理睬 服務器 的確認,也不會向 服務器 發送數據。可是 服務器 卻覺得新的運輸鏈接已經創建了,並一直等待 客戶端 發來數據。服務器 的許多資源就這樣白白浪費了。 採用三次報文握手的辦法,能夠防止上述現象的發生。假如在剛纔的異常狀況下,客戶端 不會像 服務器 的確認發出確認。服務器 因爲收不到確認,就知道 客戶端 並無要求創建鏈接。
blog
數據傳輸結束後,通訊的雙方均可以釋放資源。此時 客戶端 和 服務器 都處於 ESTABLISHED 狀態。進程
第一次握手 : 客戶端 的應用進程先向其 TCP 發出鏈接釋放報文段,並中止在發送數據,主動關閉 TCP 鏈接。客戶端把鏈接釋放報文段首部的終止控制位 FIN 置 1,其序號 seq = u ,它等於前面已傳過的數據的最後一個字節的序號加 1 。這時 客戶端 進入 FIN-WAIT-1 (終止等待1) 狀態,等待 服務器 的確認。( FIN 報文段即便不攜帶數據,它也消耗掉一個序號。)
資源
第二次握手:服務器收到鏈接釋放報文段後即發出確認,確認號 ack = u + 1 ,而這個報文段 本身的序號是 v ,等於 服務器 前面已經傳過的數據的最後一個字節的序號加 1 。而後 服務器 就進入 CLOSEWAIT(關閉等待)狀態。TCP 服務器進程這時應通知高層應用進程(不肯定本身是否還有數據要發送給 客戶端(因此是四次不是三次)),於是從 客戶端 到 服務器 這個方向的鏈接就釋放了,這時的 TCP 鏈接處於 半關閉(Half-close)狀態,即 客戶端 已經沒有數據要發送了,但 服務器 若發送數據,客戶端仍要接收。也就是說, 服務器 到 客戶端 這個方向的鏈接並未關閉,這個狀態可能會持續一段時間。
客戶端 收到來自 服務器 的確認後,就進入 FIN-WAIT-2(終止等待2) 狀態,等待 服務器 發出的鏈接釋放報文段。
第三次握手:若 服務器 已經沒有要向 客戶端 發送的數據,其應用進程就通知 TCP 釋放鏈接。這時 服務器發出的鏈接使用報文段必須使用 FIN = 1。現假設 服務器 的序號爲 w(在半關閉狀態 服務器 可能又發送了一些數據)。服務器還必須重複上次已發送過的確認號 ack = u + 1。這時 服務器 就進入 LAST-ACK (最後確認) 狀態,等待 客戶端 的確認。
第四次握手:客戶端 在收到 服務器 的鏈接釋放報文段後,必須對此發出確認。在確認報文段中把 ACK 置 1,確認號 ack = w + 1,而本身的序號是 seq = u + 1(根據 TCP 標準,前面發送過的 FIN 報文段要消耗一個序號)。而後進入到 TIME-WAIT(時間等待) 狀態。請注意,TCP 鏈接如今尚未釋放掉。必須通過 時間等待計時器(TIME-WAIT)設置的時間 2MSL 後,客戶端 才進入到 CLOSED 狀態。時間 MSL 叫作 最長報文段壽命,RFC 793 建議設爲 2 分鐘。
第一,爲了保證 客戶端 發送的最後一個 ACK 報文段可以到達 服務器。這個 ACK 報文段有可能丟失,於是使 服務器 收不到確認。服務器 會超時重傳這個 FIN + ACK 報文段,而 客戶端 就能在 2MSL 時間內收到這個重傳的報文段。接着 客戶端 重傳一次確認,從新啓動 2MSL 計時器。最後,客戶端 和 服務器 都能正常進入到 CLOSED 狀態。若是 客戶端 在 TIME-WAIT 狀態不等待一段時間,而是在發送完 ACK 報文段後當即釋放鏈接,那麼就沒法收到 服務器 重傳 的 FIN+ACK 報文段,於是也不會再發送一次確認報文段。這樣,服務器 就沒法按照正常步驟進入 CLOSED 狀態。
第二,防止「已失效的鏈接請求報文段」 出如今本次鏈接中。客戶端 在發送完最後一個 ACK 報文段後,再通過 2MSL,就可使本次鏈接持續的時間內所產生的全部報文段都從網絡中消失。這樣就可使下一個新的鏈接中不會出現這種舊的鏈接請求報文段。
TCP 設有一個 保活計時器。服務器每收到一次客戶的數據,就從新設置保活計時器,時間的設置一般是兩小時。若兩小時沒有收到客戶的數據,服務器就發送一個 探測報文段 ,之後則每隔 75 秒鐘發送一次。若一連發送 10 個探測報文段後仍無客戶的響應,服務器就認爲客戶端出了故障,接着就關閉這個鏈接。
參考:《計算機網絡》謝希仁