TCP 建立連接的前兩個報文段不包含應用層數據,第三個報文段可以承載有效數據。
建立連接以后,TCP將數據引導到該連接到發送緩存里,發送緩存是發起三次握手期間設置的緩存之一。
MSS:最大報文段長度,報文段里應用數據的最大長度。(1460-1480) 而不是包含首部的TCP報文段最大長度。
MTU:最大鏈路層幀長度,及最大傳輸單元,一般為1500字節。
TCP 報文段結構
TCP報文段由首部字段和一個數據字段組成。 MSS限制了報文段數據字段的最大長度。
TCP的首部一般是20B,Telnet發送的報文段長度也許是21B。
-
2B的 源端口號 2B的 目的端口號 :用於多路復用/分解
-
4B的序號 4B的確認號: 用於實現可靠數據傳輸
-
2B的接收窗口:用於流量控制,指示接收方願意接受的字節數量
-
2B的檢驗和: 檢驗數據傳輸是否出現bit改變
-
2B的緊急數據指針: TCP必須通知接收端的上層實體
-
4bit的 首部長度: TCP報文段的首部長度,一般為20B
-
6bit的 標志字段
- ACK : 指示確認字段中的值是有效的
- RST、SYN、FIN:連接建立和拆除
- CWR、ECE: 明確擁塞通告
這兩個在實踐的時候並沒有被使用,為了完整,記錄在下。
1. PSH:指示接收方需要立刻將數據交給上層
2. URG:指示報文段里存在着被發送段的上層實體置為“緊急”的數據

1. 序號和確認號
- TCP首部的序號和確認號是可靠傳輸服務的關鍵部分
- TCP把數據看成無結構、有序的字節流
- 序號建立在傳送的字節流上,而不是建立在傳送的報文段的序列之上
- 報文段的序號字段是該報文段數據字段首字節的序號
- 確認號是該主機 正在在等待的數據的下一字節的序號
- 客戶到服務器的數據的確認 被裝載在 服務器到客戶到數據的 報文段中: 這中確認被稱為 捎帶在服務器到客戶到數據報文中的。
TCP會對數據流中的每一個字節編號,假設數據流為500_000字節的文件組成,其中MSS=1000B,數據流的首字節編號為0。那么TCP為這個數據流構建500個報文段。給一個報文段分配序號0,第二個報文段分配序號1000,第三個報文段分配序號2000。
每一個序號被填入到相應TCP報文段首部的序號字段中。
因為是全雙工通信,主機A填充進報文段的確認號是 主機A期望從主機B收到的下一字節的序號。
假設主機A已經收到來自主機B的編號為0-535的所有字節,主機A就會在它發往主機B的報文段的確認號字段中填上536。
當主機在一條TCP連接中收到失序報文段時該怎么辦?
TCP的RFC並沒有為此明確任何規則,把這一問題留給實現TCP編程人員去處理 。
有兩個基本的選擇:
- 接收方立即丟棄失序報文段
- 接收方保留失序的字節,並等待缺少的字節以填補該間隔。該種方式是實踐中采用的方式。
初始序號可以隨機選擇,減少仍在網絡中存在的報文(主機已經終止連接了),被誤認為有效報文的可能性。
2. 往返時間的估計與超時
2.1 估計往返時間
超時間隔必須大於連接的往返時間RTT
- TCP絕不為已被重傳的報文計算SampleRTT
- TCP僅為傳輸一次的報文段測量SampleRTT
- SampleRTT : 從某報文段被發出(交IP)到對該報文的確認被收到之間的時間量。 (僅在某個時刻做一次這個測量)
- 指數加權移動平均, TCP會維護一個EstimatedRTT = (1 - alpha) * EsimatedRTT + alpha * SampleRTT, RFC 6298中 alpha = 0.125
- RTT偏差,DevRTT = (1 - beta) * DevRTT + beta * |SampleRTT - EstimatedRTT|, beta = 0.25, 波動很大的時候,DevRTT的值會很大。
2.2 設置超時時間
超時時間 TimeoutInterval = EstimatedRTT + 4 * DevRTT
推薦的初始TimeoutInterval = 1s。
出現超時后,TimeoutInterval的值會加倍。避免以及被確認的后繼報文段過早出現超時。
只要收到報文段后,就會更新新的EstimatedRTT。
隱式NAK機制: 連續收到對一個特定的報文段的3個冗余ACK可以作為對后面報文段的一個隱式NAK。
TCP使用的是
3.TCP可靠數據傳輸
TCP可靠數據傳輸服務確保: 一個進程從其接受緩存中讀出的數據是無損壞、無間隙、非冗余和按序到達的數據流。
TCP協議遵循了單一定時器的推薦: 定時器管理過程僅使用單一的重傳定時器,即有多個已發送但還未被確認的報文段。
TCP發送方有3個與發送和重傳有關的主要事件: 從上層接受數據、定時器超時和收到ACK。
- 從上層接受數據: TCP從應用接受數據,將數據封裝到一個報文段中,並把該報文段交給IP層。每一個報文段都包含一個序號,這個序號是第一個數據字節的字節流編號。 如果此時定時器沒有啟動,就啟動該定時器,過期時間間隔=TimeoutInterval。
生存TCP報文段
if 定時器沒有啟動: 啟動定時器
向IP傳遞報文段
nextseqnum = nextseqnum + length(data)
- 定時器超時
重傳具有最小序號但仍未應答的報文段
啟動定時器
- 接收ACK
因為TCP采用了累計確認,如果y > sendBase,那么ACK是在確認一個或者多個先前未被確認的報文段。
if (y > sendBase):
sendBase = y
if 仍無任何應答報文段: 啟動定時器
介紹幾種例子:
-
A->B: seq = 92, data = 8B
B ->A: ack = 100, 丟失了,
超時
A->B: seq = 92, data = 99
B->A: ack = 100,接收到, 數據會丟失

-
A-B: seq = 92, data = 8B
A-B:seq = 100, data = 20B
B-A:ack = 100
B-A: ack = 120
A-B的第一段數據報超時,然后重傳第一段,定時器重啟
B-A:ack = 100 和120到達,如果120在新的定時器超時之前到達,那么第二個報文不會被重傳。
如果ack=120到達的時候,第一個定時器沒有超時,那么第一個報文也不會進行重傳。


超時間隔加倍
當出現超時事件發生的時候,會將超時間隔設為之前的兩倍,而不是使用estimatedRTT和devRTT估算的值。
但是當另外兩個事件發生的時候,timeoutinterval 又由estimatedRTT和devRTT估算得到。
- 收到ACK
- 收到上層數據
快速重傳
超時觸發重傳存在的問題: 迫使發送方延遲重傳丟失的分組,造成了端到端的時延。
TCP接收方接收到一個數據報,其序號大於rcv_base,那么它將對最后一個按序字節數據進行重復確認(這樣就產生了一個冗余ACK)。
一旦收到3個冗余ACK,那么TCP就會執行 快速重傳,即在該報文段定時器過期之前重傳丟失的報文段。
GBN/SR?
- TCP確認是累計的,正確接收但是失序的報文時不會被接收方逐個確認的。
- TCP發送方僅需維護sendBase以及nextseqnum。
看起來和GBN風格的協議很像,但是:
- TCP實現會將正確接收但失序的報文段緩存起來。
- 如果n丟失,GBN會重傳n、n+1、... N,但是TCP只會重傳報文段n。
- 如果對報文段n+1的確認段報文在報文段n超時之前到達,TCP不會重傳這個報文段n。
RFC2018:允許TCP接收方有選擇的確認失序報文段,而不是累計確認最后一個正確接收的報文段。
