1. 程式人生 > 程式設計 >我理解的 TCP 連線

我理解的 TCP 連線

我理解的 TCP 連線-原文連結
我理解的 TCP 連線-原文連結
我理解的 TCP 連線-原文連結

總述

TCP 是面向連線的協議。運輸連線是用來傳輸 TCP 報文的。TCP 運輸連線的建立和釋放是每一次面向連線通訊中必不可少的過程。因此,運輸連線有三個階段,即:連線建立,資料傳輸和連線釋放。

在TCP連線建立過程中要解決一下三個問題。

(1)要使一方明確知道對方的存在。 (2)要允許雙方協商一些引數(如最大視窗值等)。 (3)能夠運輸實體資源進行分配。

TCP 的連線建立(三次握手)

三次握手

如上圖所示,上圖畫出了 TCP 的連線過程。假定主機 A 執行的是 TCP 客戶程式,而B執行的是 TCP 伺服器程式。最初兩端的 TCP 程式都處於 CLOSE 狀態。圖中在主機下面的方框中分別是 TCP 程式所處於的狀態。請注意,A 主動開啟連結,而 B 被動開啟連線。

B的TCP伺服器程式先建立傳輸控制快 TCB,準備接受客戶程式的連線請求。然後伺服器程式處於 LISTEN 狀態,等待客戶的連線請求。如有,即作出響應。

A的TCP客戶程式也是首先建立傳輸控制塊 TCB,然後向 B 發出連線請求報文段。這是首部的同步位 SYN = 1,同時選擇一個初始序號 seq = x。TCP 規定,SYN 報文段,不能攜帶資料,但要小號掉一個序號,這時 TCP 客戶程式進入 SYN-SEND(同步已傳送)狀態。

B接收到連線請求報文段後,如同意連線,則向 A 傳送確認。在確認報文段中應把 SYN 位和 ACK 位都設定為1,確認號是 ack = x + 1,同時也為自己選擇一個初始序號 seq = y。請注意,這個報文段也不能攜帶任何資料,但同樣要消耗掉一個序號。這時,TCP服務程式進入 SYN-RCVD(同步收到)狀態。

TCP客戶程式收到B的確認後,還要向B確認。確認報文段的ACK置1,確認號ack = y + 1,而自己的序號 seq = x + 1 。 TCP 的標準規定, ACK 報文段可以攜帶資料。但如果不攜帶資料則不消耗序號,在這種情況下,下一個資料報文段的序號仍然是 seq = x + 1。 這時 TCP 連線建立完成,A 進入 ESTABLISHED(已建立連線)狀態。 當 B 收到 A 的確認後,也進入 ESTABLISHED 狀態。

TCP 連線的釋放(四次揮手)

四次握手

資料傳輸結束後,通訊雙方都可以釋放連線。現在 A 和 B 都處於 ESTABLISHED 狀態。 A 的應用程式先向其 TCP 發出連線釋放報文段,並停止再傳送資料,主動關閉 TCP 連線。A 把連線釋放報文段首部的終止控制位置 FIN 設定為 1 ,其序號 seq = u,它等於前面傳送過程的資料的最後一個位元組序號加 1 。這時 A 進入 FIN_WAIT_1(終止等待位 1)狀態,等待 B 的確認。請注意,TCP規定,FIN 報文段即使不攜帶資料,他也消耗掉一個序號。

B 收到連線釋放的報文段後立即發出確認,確認號 ack = u + 1,而這個報文段自己的序號是 v ,等於 B 前面已傳送過的資料的最後一個位元組加 1。然後 B 進入 CLOSE_WAIT (關閉等待)狀態。TCP 伺服器程式這時通知高層的應用程式,因而從 A 到 B 這個方向的連線就釋放了,這時的 TCP 連線處於半關閉(half-close)狀態,即 A 已經沒有資料要傳送了,但是 B 若傳送資料,A 仍要接收。也就是說,從 B 到 A 這個方向的連線並未關閉,這個狀態可能會持續一段時間。

A 收到來自 B 的確認後,就進入 FIN_WAIT_2(終止等待2)狀態,等待 B 發出連線釋放報文段。

若 B 已經沒有要向 A 傳送的資料,其應用程式就通知 TCP 釋放連線。這時 B 發出連線釋放報文段使 FIN = 1。現假定 B 的序號為 w (在半關閉狀態 B 可能又傳送了一些資料)。B 還必須重複上次已經發過確認號 ack = u + 1。這時 B 就進入 LAST_ACK(最後確認)狀態,等待 A 的確認。

A 在收到 B 的連線釋放報文段後,必須對此發出確認。在確認報文段中把 ACK 設定為 1,確認號 ack = w + 1,而自己的序號是 seq = u + 1(根據 TCP 的標準,前面傳送過的 FIN 報文要消耗一個序號)。然後進入到 TIME_WAIT(時間等待)狀態。請注意,現在 TCP 連線還沒有釋放掉。必須經過時間等待計時器設定的時間 2MSL 後,A 才進入到 CLOSE 狀態。時間 MSL 叫做最長報文段壽命,RFC 793 建議設定為 2 分鐘。但這完全是從工程上來考慮,對於現在的網路,MSL = 2分鐘可能太長了一些。因此 TCP 允許不同的時間可以根據實際情況使用更小的 MSL 值。因此,從 A 進入到TIME_WAIT 狀態後,要經過 4 分鐘才能進入到 CLOSE 狀態,才能建立下一個新的連線。當 A 撤銷相應的傳輸控制塊 TCB 後,就結束這次的 TCP 連線。

兩個小問題

在三次握手的過程中,為什麼 A 還要傳送一次確認呢? 這主要是為了防止已失效的連線請求報文突然又傳到了 B,因而產生錯誤。

為什麼 A 在 TIME_WAIT 狀態必須等待 2MSL 的時間呢?

第一,為了保證 A 傳送最後一個 ACK 報文段能夠到達 B。

第二,防止剛提到的 “已失效的連線請求報文段” 出現在本連線中。A 在傳送晚最後一個 ACK 報文段後,再經過時間 2MSL,就可以使本連線持續時間內所產生的所有報文段從網路中消失。這樣就可以使下一個新的連線中不會出現這種舊的連線請求報文段。

參考連結

計算機網路第6版

關注我們

關注我們