1. 程式人生 > >TCP三次握手詳解及釋放連接過程

TCP三次握手詳解及釋放連接過程

alt 信息 情況 序列號 丟失 浪費 需要 nbsp image

TCP在傳輸之前會進行三次溝通,一般稱為“三次握手”,傳完數據斷開的時候要進行四次溝通,一般稱為“四次揮手”。

兩個序號和三個標誌位:

(1)序號:seq 序號,占 32 位,用來標識從 TCP 源端向目的端發送的字節流,發起方發送數據時對此進行標記。

(2)確認序號:ack 序號,占 32 位,只有 AC K標誌位為 1 時,確認序號字段才有效,ack = seq + 1。

(3)標誌位:共 6 個,及 URG、ACK、PSH、RST、SYNFIN 等,具體含義如下:

(A)URG:緊急指針(urgent pointer)有效。

(B)ACK:確認序號有效。

(C)PSH:接收方應盡快將這個報文交給應用層。

(D)RST:重置連接。

(E)SYN:發起一個新連接。

(F)FIN:釋放一個連接。

需要註意的是:

(A)不要將確認序號 ack 與標誌位中的 ACK 搞混了。

(B)確認方 ack = 發起方req + 1,兩端配對。

技術分享圖片

在第一次消息發送中,A 隨機選取一個序列號座位自己的初始序號發送給 B;

第二次消息 B 使用 ack 對 A 的數據包進行確認,因為已經收到了序列號為 x 的數據包,準備接收序列號為 x + 1 的包,所以 ack = x + 1,同時 B 告訴 A 自己的初始序列號,就是 seq = y;

第三條消息 A 告訴 B 收到了 B 的確認消息並準備建立連接,A 自己此條消息的序列號是 x + 1,所以 seq = x + 1,而 ack = y + 1 是標識 A 正準備接收 B 序列號為 y + 1 的數據包。

  為什麽 A 還要發送一次確認呢?這主要是為了防止已失效的連接請求報文段突然又傳送到了 B ,因而產生錯誤。

  所謂“已失效的連接請求報文段”是這樣產生的。

  考慮一種正常情況:A 發出連接請求,但因連接請求報文丟失而未收到確認。於是 A 再重傳一次連接請求。後來收到了確認,建立了連接。數據傳輸完畢後,就釋放了連接。A 共發送了兩個連接請求報文,其中第一個丟失,第二個到達了 B。沒有“已失效的連接請求報文段”。

  現假定出現一種異常情況:即 A 發出的第一個連接請求報文段並沒有丟失,而是在某些網絡結點長時間滯留了,以致延誤到連接釋放以後的某個時間才到達 B。本來這是一個早已失效的報文段。但 B 收到此失效的連接請求報文段後,就誤認為是 A 又發出一次新的連接請求。於是就向 A 發出確認報文段,同意建立連接。假定不采用三次握手,那麽只要 B 發出確認,新的連接就建立了。

  由於現在 A 並沒有發出建立連接的請求,因此不會理睬 B 的確認,也不會向 B 發送數據。但 B 卻以為新的運輸連接已經建立了,並一直等待 A 來發數據。B的許多資源就這樣白白浪費了。

  采用三次握手的辦法可以防止上述現象的發生。例如在剛才的情況下,A 不會向 B 的確認發出確認。B 由於收不到確認,就知道 A 並沒有要求建立連接。

四次揮手:

由於 TCP 連接是全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個 FIN 來終止這一方向的連接。

收到一個 FIN 只是意味著這一方向上沒有數據流動了,即不會再收到數據了,但是在這個 TCP 連接上仍然能夠發送數據,直到這一方向也發送了 FIN。

首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。

(1)第一次揮手:Client 發送一個 FIN,用來關閉 Client 到 Server 的數據傳送,Client 進入 FIN_WAIT_1 狀態。

(2)第二次揮手:Server 收到 FIN 後,發送一個 ACK 給 Client,確認序號為收到序號 + 1(與 SYN 相同,一個 FIN 占用一個序號),Server進入 CLOSE_WAIT狀態。

(3)第三次揮手:Server 發送一個 FIN,用來關閉 Server 到 Client 的數據傳送,Server 進入 LAST_ACK 狀態。

(4)第四次揮手:Client 收到 FIN 後,Client 進入 TIME_WAIT 狀態,接著發送一個 ACK 給 Server,確認序號為收到序號 + 1,Server進入 CLOSE狀態,完成四次揮手。

技術分享圖片

為什麽建立連接是三次握手,而關閉連接卻是四次揮手呢?

  這是因為服務端在 LISTEN 狀態下,收到建立連接請求的 SYN 報文後,把 ACK 和 SYN 放在一個報文裏發送給客戶端。而關閉連接時,收到對方的 FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方也未必全部數據都發送給對方了,所以己方可以立即 close,也可以發送一些數據給對方後,再發送 FIN 報文給對方來表示同意現在關閉連接。因此,己方 ACK 和 FIN 一般都會分開發送。

為什麽 TIME_WAIT 狀態需要經過 2MSL(最大報文段生存時間)才能返回到 CLOSE 狀態?

不應該是未了防止 B 發送的 FIN = 1的包的丟失,因為如果 A 沒有收到來自 B 的釋放請求連接,是不會進入 TIME_WAIT 狀態的。

所以正確的解釋是:A 發送的確認釋放連接信息 B 沒有收到,這時候 B 會再發送一個 FIN = 1的釋放連接請求,而這個時候 A 還處於 TIME_WAIT,所以可以再次發送確認信息。

TCP三次握手詳解及釋放連接過程