TCP協議圖文秒懂

codeGoogle發表於2018-02-06

本文將簡單介紹tcp協議的基本內容,主要包括一下四部分:

  • tcp概述

  • TCP可靠資料傳輸

  • TCP流量控制

  • TCP連線管理

  TCP概述

  • tcp是一個點對點端到端的傳輸協議,有一個傳送方和接收方。

  • tcp傳輸的是可靠的按序到達的位元組流

  • tcp採用流水線機制,提高傳輸的效率。TCP通過擁塞控制和流量控制機制來控制滑動視窗的大小

  • tcp協議分別設定了傳送方快取和接收方快取

TCP協議圖文秒懂

  • tcp採取全雙工(full-duplex)傳輸,也就是傳輸過程中,同一連線可以傳輸雙向的資料流,傳送方可以傳給接收方,接收方也可以傳給傳送方。

  • tcp是面向連線的協議,通訊雙方在傳送資料之前必須建立連線。連線狀態只在連線的兩端中維護,在沿途節點中並不維護狀態。TCP連線包括:兩臺主機上的快取、連線狀態變數、socket等

  • tcp實現了流量控制機制

  TCP段結構

TCP協議圖文秒懂

  TCP: 序列號和ACK

  序列號:

  • 序列號指的是segment中第一個位元組的編號,而不是segment的編號

  • 建立TCP連線時,雙方隨機選擇序列號

  ACKs:

  • 希望接收到的下一個位元組的序列號

  • 累計確認:該序列號之前的所有位元組均已被正確接收到

  Q: 接收方如何處理亂序到達的Segment?

  • A: TCP規範中沒有規定,由TCP的實現者做出決策

TCP協議圖文秒懂

  上圖我們進行一個分析,以便搞清楚tcp序列號和ack的應用

  首先,hostA作為傳送方給B傳送資料,隨機選擇一個序列號seq = 42,也就是這段segment中的第一個位元組的編號,並且設定ack=79,這表示,希望接收方回傳seg=79作為確認訊號代表接收方已經正確接受了這段資料

  然後HostB成功接收到資料,想傳送方返回確認資訊,根據傳送方的ack,所以確認的seg=79,然後通過ack告知希望接收到的下一個位元組的序列號,並同時表示之前的所有位元組均已被正確接收,所以傳送ack=43告知已經接收到43號之前的位元組,並希望傳送方傳送43號位元組

  TCP可靠資料傳輸

  接下來我們看看tcp協議是如何實現可靠傳輸的。

  • TCP在IP層提供的不可靠服務基礎上實現可靠資料傳輸服務

  • 流水線機制

  • 累積確認

  • TCP使用單一重傳定時器

  • 觸發重傳的事件:超時和收到重複ACK

  RTT和超時

  問題:如何設定定時器的超時時間?

  • 大於RTT, 但是RTT是變化的

  • 過短:不必要的重傳

  • 過長: 對段丟失時間反應

  問題:如何估計RTT?

  SampleRTT: 測量從段發出去到收到ACK的時間忽略重傳

  SampleRTT變化,測量多個SampleRTT,求平均值,形成RTT的估計值EstimatedRTT

  EstimatedRTT = (1- ?)EstimatedRTT + ?SampleRTT

  指數加權移動平均

  典型值:0.125

  TCP傳送方事件

  從應用層收到資料後,會進行以下幾個步驟:

  • 建立segment

  • 序列號是segment第一個位元組的編號

  • 開啟計時器

  • 設定超時時間TimeOutInterval

  如果發生超時事件:

  • 重傳引起超時的segment

  • 重啟計時器

  收到ACK:

  • 如果確認此前未確認的Segment,更新SendBase,如果視窗中還有未被確認的分組,重新啟動定時器

  傳送端偽碼

`

  TCP重傳示例

TCP協議圖文秒懂

NextSeqNum = InitialSeqNum  
SendBase = InitialSeqNum  
loop (forever) {  
switch(event)  
event: data received from application above  
create TCP segment with sequence number NextSeqNum  
if (timer currently not running)  
start timer  
pass segment to IP  
NextSeqNum = NextSeqNum + length(data)  
event: timer timeout  
retransmit not-yet-acknowledged segment with  
smallest sequence number  
start timer  
event: ACK received, with ACK field value of y  
if (y > SendBase) {  
SendBase = y  
if (there are currently not-yet-acknowledged segments)  
start timer  
}  
} /* end of loop forever */  
複製程式碼

TCP協議圖文秒懂

TCP協議圖文秒懂

  快速重傳機制

  TCP的實現中,如果發生超時,超時時間間隔將重新設定,即將超時時間間隔加倍,導致其很大,重發丟失的分組之前要等待很長時間.

  通過重複ACK檢測分組丟失,Sender會背靠背地傳送多個分組,如果某個分組丟失,可能會引發多個重複的ACK.

  如果sender收到對同一資料的3個ACK,則假定該資料之後的段已經丟失.

  快速重傳:在定時器超時之前即進行重傳

  演算法

C++程式碼

event: ACK received, with ACK field value of y  
if (y > SendBase) {  
SendBase = y  
if (there are currently not-yet-acknowledged segments)  
start timer  
}  
else {  
increment count of dup ACKs received for y  
if (count of dup ACKs received for y = 3) {  
resend segment with sequence number y  
}
複製程式碼

TCP流量控制

  接收方為TCP連線分配buffer

TCP協議圖文秒懂

  上層應用可能處理buffer中資料的速度較慢

  流量控制:傳送方不會傳輸的太多、太快以至於淹沒接收方(buffer溢位)

  (假定TCP receiver丟棄亂序的segments)

Buffer中的可用空間(spare room) = RcvWindow 

 = RcvBuffer-[LastByteRcvd -LastByteRead]
複製程式碼

  Receiver通過在Segment的頭部欄位將RcvWindow 告訴Sender。 Sender限制自己已經傳送的但還未收到ACK的資料不超過接收方的空閒RcvWindow尺寸。

  Receiver告知SenderRcvWindow=0,會出現什麼情況?

  會出現卡死,傳送方不發資料了。關於這些問題具體會在tcp擁塞控制裡面討論。

  TCP連線管理

  TCP sender和receiver在傳輸資料前需要建立連線。

三次握手機制

  第一次握手: client host sends TCP SYN

  segment to server

  • specifies initial seq #

  • no data

第二次握手: server host receives SYN, replies

  with SYNACK segment

  • server allocates buffers

  • specifies server initial seq. #

第三次握手: client receives SYNACK, replies

  with ACK segment, which may

  contain data

TCP協議圖文秒懂

  四次握手機制

  TCP連線管理:關閉

  Step 1: client向server傳送TCP FIN 控制segment

  Step 2: server 收到FIN, 回覆ACK. 關閉連線, 傳送

  FIN.

  Step 3: client 收到FIN, 回覆ACK.

  • 進入“等待” –如果收到FIN,會重新傳送ACK

  Step 4: server收到ACK. 連線關閉.

TCP協議圖文秒懂

  由於TCP連線是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的資料傳送任務後就能傳送一個FIN來終止這個方向的連線。收到一個 FIN只意味著這一方向上沒有資料流動,一個TCP連線在收到一個FIN後仍能傳送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

(1) TCP客戶端傳送一個FIN,用來關閉客戶到伺服器的資料傳送(報文段4)

(2) 伺服器收到這個FIN,它發回一個ACK,確認序號為收到的序號加1(報文段5)。和SYN一樣,一個FIN將佔用一個序號

(3) 伺服器關閉客戶端的連線,傳送一個FIN給客戶端(報文段6)

(4) 客戶段發回ACK報文確認,並將確認序號設定為收到序號加1(報文段7)

更多閱讀

為什麼成為一名程式設計師這麼困難? — 從程式新手到準工程師的必經之路

給應用開發者程式設計的十一條個建議

相信自己,沒有做不到的,只有想不到的

微信公眾號:終端研發部

技術

相關文章