一、 停止等待 (stop-and-wait) 協議的低帶寬利用率
舉一個例子來說明。假設兩個主機分布在美國東西海岸,他們之間的光速傳播往返時延 RTT 大約是30毫秒。這兩個主機通過一條發送速率(即帶寬)是 1Gbps 的信道相連。數據的分組長 L 是 1000 字節,發送一個分組進入信道的時間是:
\[ t_{trans} = \frac{L}{R} = \frac{8000bit/pkt}{10^9bit/s} = 8\mu s/pkt\]
如果發送方在 \(t=0\) 時刻開始發送分組,則在 \(8\mu s\) 后,最后1bit進入了發送端信道。經過 \(15ms\) 后,分組的第一個 bit 到達接收端;在 \(15.008ms\) 時刻,分組的最后一個 bit 到達接收端。假設接收端的 ACK 產生和發送不占用時間,則再經過 \(15ms\) 以后,即 \(t=30.008ms\),發送端接收到接收端的ACK,發送端可以發送下一個分組。
在 \(30.008ms\) 內,發送方的發送使用了 \(0.008ms\)。我們定義信道利用率為:發送方實際忙於發送比特到信道的時間與發送時間之比,則停止等待協議的發送方利用率為:
\[U_{sender} = \frac{L/R}{RTT+L/R} = \frac{0.008}{30.008} = 0.00027\]
這是一個網絡協議限制底層網絡硬件所提供的能力的例子。
二、流水線傳輸協議
解決上述問題的一個方法是:不適用停止等待方式,運行發送方發送多個分組而無需等待確認。由於許多從發送方向接收方輸送的分組可以被看成是填充到一條流水線中,因此這種技術被稱為流水線 (pipelining)。當然,流水線會增加協議的復雜度:
- 必須增加序號范圍
因為信道中的分組要有一個唯一的序號,會有多個分組在信道中未被確認。 - 協議的發送方和接收方必須緩存多個分組
發送方至少應該緩存已經發送卻還沒有被確認的分組。接受方也許應該緩存已經正確接收的分組。 - 所需的序號范圍和對緩存大小的要求取決於協議如何處理丟失、損壞及延時大的分組
解決流水線差錯錯誤的兩種基本思路:回退N步和選擇重傳。
2.1 回退N步 (Go-Back-N)
主要特點是如果接收方丟棄所有失序分組。
我們先來看下回退N部協議的基本原理。
對於發送方來說,每個分組都有一個序號。在每一個時刻,發送方維護幾個變量:
- 基序號 (base)
最早的未確認分組的序號。 - 下一個序號 (nextseqnum)
最小的未使用序號,也是下一個待發送分組的序號。 - 窗口長度 (window size) N
根據這三個變量,將序號范圍分隔為4段:
- [0, base-1]
已經發送並被確認的分組。 - [base, nextseqnum -1]
已經發送但未被確認的分組。 - [nextseqnum, base + N -1]
要立即被發送的分組。 大於等於 base + N
不能使用的,直至當前流水線中未被確認的分組已得到確認為止。
 已經被發送但還未被確認的分組的許可序號范圍可以被看成是一個序號范圍長度為N的窗口。隨着協議的運行,該窗口在序號空間向前滑動。因此 GBN 協議被稱為滑動窗口協議 (silding-window protocol)。有長度N的限制是為了進行流量控制。
基於 ACK、無 NAK 的 GBN 協議的發送方 FSM 如下:

GBN 發送方相應三種類型的事件:
- 上層調用
即上層調用rdt_send()。如果窗口未滿,則產生一個分組,並將其發送,並更新狀態。否則把數據返回上層,告知其窗口已滿。 - 收到一個ACK
GBN 協議采用累積確認 (cumulative acknowledgement) 的方式,即收到序號 \(n\) 的ACK, 表明接收方已經收到序號 \(n\) 及之前的所有分組。
如果收到一個ACK,但仍有未被確認的分組,則重啟定時器。
如果沒有已發送但未被確認的分組,終止定時器。 - 定時器超時
發送方將重傳所有已發送但未被確認的分組。發送方僅使用一個定時器,可被當做最早的已發送但未被確認的分組所使用的定時器。
GBN 接收方的 FSM 如下:

接收方的響應很簡單。如果一個序號為 \(n\)的分組被正確接收到,並且按序(上一個接收到的分組是序號 \(n-1\)),則發送一個序號為 \(n\) 的ACK給發送方,並把該分組交付上層。其他情況下都是丟棄接收到的分組,並為最近按序接收的分組重新發送 ACK。
GBN協議的優缺點
- 優點
接收緩存簡單,即接收方不需要緩存任何失序分組。接收方需要維護的唯一信息就是下一個按序接收的分組的序號,即 FSM 中的expectedseqnum變量。 - 缺點
會丟棄已經正確接收的分組。對該分組的重傳也許會丟失或出錯,因此甚至需要更多的重傳。也會加大對整個網絡的壓力。
當帶寬時延積很大時,單個分組的差錯就能引起 GBN 重傳大量分組,而許多分組根本沒有必要重傳。隨着信道差錯率的增加,信道可能會被這些沒有必要重傳的分組充斥。
2.2 選擇重傳 (Selective Repeat, SR)
選擇重傳協議讓發送方僅重傳那些它懷疑在接收方出錯的分組,避免了不需要的重傳。
SR 發送方
下圖顯示了 SR 發送方看到的序號空間。

如上圖所示,發送方已經收到了窗口中某些分組的 ACK。窗口長度 N 仍被用來限制流水線中未完成、未被確認的分組數量。
SR 發送方采取的動作如下:
- 從上層收到數據
發送方檢查下一個可用於該分組的序號。如果序號在發送方窗口內,則發送該分組,否則將其返回上層或緩存以便以后傳輸。 - 超時
每個分組都必須擁有自己的邏輯定時器,定時器用來防止丟失分組。
可以用單個硬件定時器模擬多個邏輯定時器操作。 - 收到 ACK
如果收到 ACK 的分組序號在窗口內,則發送方將那個被確認的分組標記為已接受。
如果分組序號為 send_base,則窗口基序號向前移動到具有最小序號的未確認分組處。
如果窗口移動了並且有序號落在窗口的未發送分組,則發送這些分組。
SR 接收方
接收方將確認一個正確接收的分組而不管其是否按序。失序的分組將被緩存直到所有丟失分組(即序號更小的分組)皆被收到為止。此時把這一批分組按序交付給上層。
- 序號在 [rcv_base, rcv_base + N -1] 內的分組被正確接收
即收到的分組落在接收方窗口內,一個 ACK 被回送到發送方。
如果該分組沒有收到過,則緩存該分組。
如果該分組的序號等於接收窗口的基序號 (rcv_base),則將該分組以及之前緩存的序號連續的分組交付給上層,然后接收窗口向前移動。 - 序號在 [rcv_base -N, rcv_base -1] 內的分組被正確收到
必須產生一個 ACK, 即使該分組是接收方已經確認過的分組。 - 其他情況
忽略分組
值得注意的是,在第 2 種情況下,接收方重新確認已收到過的那些序號小於當前窗口基序號的分組。這種重新確認是有必要的,因為 ACK 可能會丟失或損壞。
比如分組 send_base 的 ACK 沒有從接收方傳播會發送方,那么發送方會重傳分組 send_base。如果接收方不確認該分組,則發送方窗口將永遠不能向前滑動!
對於 SR 協議來說,發送方和接收方的窗口並不總是一致。
三、 其他一些事情
- TCP 使用的是 GBN 協議和 SR 協議的混合體
- 窗口長度必須小於等於序號空間大小的一半
- 分組可能被重新排序
由於兩台主機不是直接連接的,不同分組經過的路由不同,而且路由器可能會復制多份分組。因此分組在發送方和接收方之間的信道可能被重新排序。
一個表現就是一個具有序號或區分號 \(x\) 的分組的舊副本可能重新出現,即使發送方或接收方的窗口中都沒有包含 \(x\)。
實際中為了避免出現這種冗余分組,采取的措施是:確保一個序號不被重新使用,直到發送方“確信”任何先前發送的序號為 \(x\) 的分組都不再出現在網絡中。通過假定一個分組在網絡中的“存活”時間不會超過某個固定最大時間量,對於 TCP 來說,這個值被假定為 3 分鍾。
四、來源
- Kurose, KeithW.Ross, 庫羅斯,等. 計算機網絡:自頂向下方法[M]. 高等教育出版社, 2009.
