# TCP - Connection Establishment & Termination [TOC] ## 課程影片 ### How TCP Works - The Handshake {%youtube HCHFX5O1IaQ %} ### How TCP Works - FINs vs Resets {%youtube -vgk9P-6dPY %} ### 第 8E 講 TCP 與網路阻塞偵測與控制技術 L08 5 {%youtube 6nAC8obhsqc %} ## 發起連線前:Client 初始化 `seq` 與 `window` *TCP* 是連線導向的傳輸協定,所以在傳輸資料之前,要先建立連線。為了方便,以下稱呼發起連線的一方為 *client*,而另外一方則稱其為 *server*。 因為 *TCP* 使用 *sliding window* 進行可靠傳輸,所以使用 *sliding window* 演算法所需要的第一個 *sequence number* (這邊的 `seq`) 要先決定好。除此之外,*TCP* 封包中的 `window`,也就是「允許發送方發送能傳送多少資料」的額度,也應一併決定好,以利 *flow control*。 ## 連線建立:三方交握  前述都準備好之後,就準備開始建立連線。建立連線時,使用一系列稱為「三方交握」(*three-way hand shake*)的步驟。這個步驟細分為以下三步: ### Step 1:Client 發出 SYN 封包 首先,*Client* 會發送一個特殊的 SYN 封包給 *Server*。這是一個沒有資料,但其中的「`syn` 欄位被設為 `1`」的封包。除此之外,因為兩者藉由 *TCP* 傳輸時,使用的是*sliding window*,所以也要在這個封包中的 `seq` 欄位中,指定好「初始的 *sequence number*」。 ### Step 2:Server 回應 SYN/ACK 封包確認 如果 *Server* 有收到這個 SYM 封包,確定要建立連線並且設置好 *buffer* 之後,必須回覆給 *Client* 一個「`syn` 與 `ack` 都設為 `1`」的封包,這個封包稱為 SYN/ACK 封包。 這個 SYN/ACK 封包中,除了前述 2 個位元被設為 `1` 之外,他的 `ack_seq` 與 `seq` 也要設定: 1. `ack_seq`:因為使用 *sliding window* 時,ACK 必須回報「在哪個 *sequence number* 以前的封包都收到了」,所以這個 `ack_seq` 欄為要設定為剛剛 SYN 封包上的 `seq` 欄位加 1。 2. 因為 *Server* 也可能向 *Client* 傳輸資料,而這個傳輸過程也要使用 *sliding window*。所以這個 SYN/ACK 封包中的 `seq`,還要包含 *Server* 自己使用 *sliding window* 演算法時,所需要的那個初始化 *sequence number* ### Step 3:Client 回應 ACK 封包 當 *Client* 收到 SYN/ACK 封包之後,接著往 *Server* 傳輸一個 ACK。這時這個封包中就可以包含要傳輸的資料了。 ### 一些註解 在這個演算法中,從 *Server* 與 *Client* 都各自經歷了「送一個 SYN 與回收一個 ACK」。而彼此 `seq` 與 `ack_seq` 的關係可以用以下的動畫展示:  ## 結束連線 結束連線的請求可以由 *Client* 提出,也可以由 *Server* 提出。以下假定是 *Client* 發起結束連線的請求。  ### Step 1:Client 送出 FIN 封包 首先,由希望結束連線的一方送出(這邊是 *Client*) FIN 封包。這個封包是一個 `fin` 欄位被設定的封包。 ### Step 2:Server 回覆 ACK 如果 *Server* 有收到這過 SYN 封包,那麼就要回覆一個 ACK。並且準備開始結束連線。 ### Step 3:Server 送出 FIN 封包 因為 *TCP* 的溝通是雙向的,所以要終止連線,除了 *Client* 要跟 *Server* 發出終止連線的請求之外,*Server* 也要跟 *Client* 發出終止連線的請求。因此也要向 *Client* 發送一個 FIN 封包。 在發送 FIN 封包之後,*Server* 進入一個 *Closing* 狀態。這是一個「準備結束」,但是還沒有結束的狀態。要一直等到 *Client* 回了 ACK,整個連線對 *Server* 來說才是結束(也就是進入 *Close* 狀態)。 ### Step 4:Client 回覆 ACK *Client* 在收到 FIN 封包之後,回覆 ACK。並且自己也進入 *Closing* 狀態。 ### Step 5:Client 等待一段時間 在 *Client* 進入 *Closing* 狀態之後,還必須等待一段時間,才能結束。因為這時可能還有封包在路上,所以要等待一段時間讓他們送達。這段時間通常是 30 秒。 ## 連線狀態圖 如果把連線建立的狀態化成狀態圖的話,彼此的關係如下[^state]:  > 按:課程影片中所泛稱的 *Closing* 狀態,應係圖中的 `FIN_WAIT2` 與 `LAST_ACK`,而非圖中的 `CLOSING`。 [^state]: 維基百科 (https://zh.wikipedia.org/wiki/File:Tcp_state_diagram_fixed_new.svg) ## Wireshark Tips ### Inside the TCP Handshake (Sharkfest 2013) {%youtube HGcbhCVZ8MU %}
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up