計算機網路 自頂向下方法 第三章 運輸層
阿新 • • 發佈:2018-12-31
Tags:計算機網路
第三章 運輸層
3.1 概述和運輸層服務
3.1.1 運輸層和網路層的關係
- 網路層提供了 主機 之間的邏輯通訊。而運輸層為執行在 不同主機上的程序 提供邏輯通訊。
- 運輸層協議只工作在端系統上。
- 運輸協議能提供的服務受制於底層網路協議的服務模型。
- 網路層協議,即 IP 協議,其服務模型是 盡力而為交付服務 ,但不做任何的保證。是 不可靠服務 。
3.1.2 因特網運輸層概述
- UDP 提供了一種不可靠、無連線的服務。
- TCP 提供了一種可靠的、面向連線的服務。
- 程序到程序的資料交付和差錯檢測是兩種最低限度的運輸層服務,也是 UDP 能提供的僅有的兩種服務。
3.2 多路複用與多路分解
- 多路分解: 將運輸層報文段中的資料交付到正確的套接字。
- 多路複用: 在源主機從不同的套接字中收集資料塊,併為每個資料塊封裝上首部資訊從而生成報文段,然後將報文傳遞到網路層。
- 運輸層多路複用要求:
- 套接字有唯一識別符號。
- 每個報文段有特殊字元(埠號)來指示該報文段所要交付到的套接字。
- 埠號:一個 16 位元的數,在 0 ~ 65535 之間。其中 0 ~ 1023 是周知埠號,是受限制的。
3.2.1 無連線的多路複用與多路分解
- 用
clientSocket = socket(socket.AF_INET, socket.SOCK_DGRAM)
也可以用clientSocket.bind(('',23333))
顯式的分配一個埠號。 - 通常,應用程式的客戶端讓運輸層自動地分配埠號,而伺服器則分配一個特定的埠號。
- 一個 UDP 套接字是由一個包含 目的 IP 地址 和 目的埠號 的 二元組 標識的。
3.2.2 面向連線的多路複用與多路分解
- TCP 套接字是由一個 四元組(源 IP 地址,源埠號,目的 IP 地址,目的埠號)來標識的。
3.3 無連線運輸:UDP
- 選擇 UDP 的原因:
- 關於何時、傳送什麼資料的應用層控制更為精細。
- 無需連線建立。
- 無連線狀態。
- 分組首部開銷小。
- 用 UDP 建立可靠資料傳輸機制可以在應用層中實現。
3.3.1 UDP 報文結構
- 首部只有 4 個欄位,每個欄位 2 位元組。其中,length 指示了 UDP 報文段中的 首部加資料的位元組數。
3.3.2 UDP 檢驗和(上圖中的 checksum)
- 檢驗和 是 UDP 的差錯檢測機制。其實現方法是:
- 將 UDP 報文按 16 位元進行分組。
- 將兩個 16 位元的數字相加得到一個 32 位的數。
- 將 2 中得到的 32 位元數的 高 16 位和低 16 相加。
- 重複第 2 步直到得到的和的高 16 位為 0。
- 將得到的 16 位元的數按位取反即為 檢驗和。
- 注:計算之前的檢驗和為 0
- 如果傳輸沒有出錯,則在接收方處計算的的檢驗和將是
11111111111111
。若不是,則資料有錯。
3.4 可靠資料傳輸原理
3.4.1 構造可靠資料傳輸協議
在這節將一步步研究一系列協議,它們一個比一個複雜,最後得到一個無錯、完全可靠的資料傳輸協議。
1. 經完全可靠通道的可靠傳輸協議: rdt 1.0
- 這是最簡單的情況,假設底層通道是完全可靠的。
- 有限狀態機(FSM):
- 箭頭指示了協議從一個狀態變遷到另一個狀態。
- 引起變遷的事件顯示在橫線的上方。
- 事件發生時所採取的動作顯示在橫線的下方。
- ^ 表示什麼都不做。
下圖是傳送方和接收方的 有限狀態機:
- 傳送方:
rdt_send(data)
: 接收較高層的資料。make_pkt(data)
: 將資料打包成分組。udt_send(packet)
: 將分組傳送到通道中。
- 接收方:
rdt_rcv(data)
: 從底層通道接收一個分組。extract(packet,data)
: 從分組中取出資料。deliver_data(data)
: 將資料傳送給較高層。
2. 經具有位元差錯通道的可靠資料傳輸:rdt 2.0
- 假設底層通道傳輸的資料可能會有位元差錯。但是仍然不會丟包。
- 在接收方的協議中加入:
- 差錯檢測
- 接收方反饋
- 肯定確認(ACK)
- 否定確認(NAK)
- 重傳
接收到有差錯的分組時,傳送方重傳該分組。
- 下圖是 rdt 2.0 的 FSM:
- 當傳送方處於等待 ACK 或 NAK 的狀態時,它不能從上層獲得資料。這被稱為 停等協議。
2.1 rdt 2.1
- rdt 2.0 中有一個致命的缺陷,就是沒有考慮到 ACK 和 NAK 分組受損的可能性。
- 解決這個新問題的一個簡單的方法就是在資料分組中新增一個欄位,讓傳送方對其資料分組編號,即將傳送資料分組的 序號 放在該欄位。
- 於是,接收方只需要檢查序號即可確定收到的分組是否一次重傳。
- 對於停等協議這種簡單的情況,1 位元的序號就足夠了。
- 下圖是 rdt 2.1 的 FSM:
2.2 rdt 2.2
- 當收到受損的分組時,rdt 2.0 的接收方會發送一個否定確認 NAK。
- 如果不傳送NAK,而是對上次正確接收的分組傳送一個 ACK,則也能實現和 NAK 一樣的效果。
- 下圖是 rdt 2.2 的 FSM:
3. 經具有位元差錯的丟包通道的可靠資料傳輸:rdt 3.0
- 現在假定除了位元受損外,底層通道還會丟包。
- 在 rdt 3.0 中,丟包的問題讓傳送方解決。不管是傳送的分組丟失,還是接收方返回的確認分組丟失,只要在經過一定的時延後,讓傳送方重發該分組即可。由此產生的 冗餘資料分組 則由接收方通過序號處理。
- 下圖是 rdt 3.0 傳送方的 FSM:
- 因為分組序號在 0 和 1 之間交替,因此 rdt 3.0 有時被稱為 位元交替協議。
3.4.2 流水線可靠資料傳輸
- rdt 3.0 是一個功能正確的協議,但是由於它是一個停等協議,大部分的時間都浪費在等待確認上面,所以效能不好。
- 解決這種特殊效能問題的一個簡單的方法是:不使用停等方式執行,允許傳送方傳送多個分組而無需等待確認。這種技術被稱為 流水線。
- 要使用流水線技術,則須:
- 增加序號範圍。因為要傳送多個分組,而每個傳輸中的分組必須有一個單獨的序號。
- 協議的傳送方和接收方兩端必須能快取多個分組。傳送方至少得能快取那些已傳送但未確認的分組,而接收方或許也需要快取那些已經正確接收的分組。
- 所需序號的範圍和對緩衝的要求取決於資料傳輸協議如何處理丟失、損壞及延時過大的分組。
- 流水線的差錯恢復有兩種基本方法:
- 回退 N 步
- 選擇重傳
3.4.3 回退 N 步(GBN)
- 在 回退 N 步協議 中,允許傳送方傳送多個分組而不需等待確認,但它也受限於在流水線中未確認的分組數不能超過某個最大允許數 N。
- 基序號(base)為最早的未確認分組的序號。
- 下一個序號(nextseqnum)為下一個待發分組的的序號。
- N 常被稱為 視窗長度,GBN 協議也常被稱為 滑動視窗協議。
- 在實踐中,一個分組的序號承載在分組首部的一個固定長度的的欄位中。
- 如果該欄位的位元數是 k ,則該序號範圍是
[0,2k−1] ,是一個長度為2k 的環。 - 下圖是 GBN 傳送方的擴充套件 FSM 描述:
- GBN 的傳送方必須響應三種類型的事件:
- 上層的呼叫:若視窗未滿,則產生一個分組將其傳送。
- 收到一個 ACK:對序號為 n 的分組的確認採取 累積確認,表明接收方已正確接收到包括 n 的序號在內的 n 的以前的所有分組。
- 超時事件:只使用一個定時器,即最早的已傳送但未被確認的分組所使用的定時器。如果出現超時,則傳送方重傳所有已傳送但還未被確認的分組。如果收到一個 ACK,但仍有已傳送但未被確認的分組,則重啟定時器。如果沒有已傳送但未確認的分組,該定時器被終止。
- GBN 的傳送方必須響應三種類型的事件:
- 下圖是GBN 接收方的擴充套件 FSM 描述:
- 如果一個序號為 n 的分組被正確收到,並且按序(上次交付給上層的資料的序號是 n-1),則接收方為分組 n 傳送一個 ACK,並將該分組中的資料交付到上層。在其他所有情況下,接收方丟棄該分組。併為最近按序接收的分組重新發送 ACK。
3.4.4 選擇重傳(SR)
- GBN 也存在一些效能問題,單個分組的錯誤會引起大量分組的重傳。
- 選擇重傳 通過讓傳送方僅重傳那些它懷疑在接收方出錯的分組而避免了不必要的重傳。
- 下圖是選擇重傳發送方和接收方的序號空間:
- SR 傳送方的事件和動作:
- 從上層接收資料: 檢查下一個可用於該分組的序號,若在傳送方的視窗內,則將資料打包傳送。
- 超時: 定時器再次用來防止丟失分組。但是現在每個分組必須得有單獨的定時器。
- 收到 ACK:倘若該分組序號在視窗內,則 SR 傳送方將那個被確認的分組標記為已接收。如果該分組的序號等於send_base,則視窗基序號向前移動到具有最小序號的未確認分組處。如果視窗移動了並且該序號落在視窗內的未傳送分組,則傳送這些分組。
- SR 接收方將確認一個正確接收的分組而不管其是否按序。
SR 接收方的事件於動作:
- 序號在 [rcv_base, rcv_base + N -1] 內的分組被正確接收:在此情況下,收到的分組落在接收方的視窗內,一個選擇 ACK 被回送給傳送方。如果該分組以前沒收到過,則快取該分組。如果該分組的序號等於接收視窗的基序號,則該分組及以前快取的序號連續的分組交付給上層。
- 序號在 [rcv_base - N, rcv_base - 1] 內的分組被正確接收: 產生一個 ACK,即使該分組是接收方以前已確認過的分組。
- 其他情況:忽略該分組。
視窗長度必須小於或等於序號空間大小的一半。
3.5 面向連線的運輸:TCP
3.5.1 TCP 連線
- 由於 TCP 協議只在端系統中執行,而不在中間的網路元素(路由器和鏈路層交換機)中執行,所以中間的網路元素不會維持 TCP 連線狀態,不會為該連線分配任何快取和變數。其連線狀態完全保留在兩個端系統中。
- TCP 連線提供的是 全雙工服務。
- TCP 建立連線需要 三次握手,其中,前兩次握手不承載”有效荷載“,第三次握手可以承載有效荷載。
- 通過套接字傳送資料過程如下圖:
- TCP 將資料引導到該連線的 傳送快取 裡,接下來 TCP 就會不時地從傳送快取裡取出一塊資料。
- TCP 可從快取中取出並放入報文段的資料數量受限於 最大報文段長度(MSS)。該長度是指報文段裡應用層資料的最大長度,而不是包括 TCP 首部的 TCP 報文段的最大長度。
3.5.2 TCP 報文結構
- 16 位元的 源埠號 和 16 位元的目的 埠號。用於多路分解和多路複用。
- 32 位元的 序號(sequence number)欄位。一個報文段的序號 是該報文段資料欄位首位元組的序號。
- 32 位元的 確認號(Acknowledgement number)欄位。主機 A 填充進報文段的確認號是主機 A 期望從主機 B 收到的下一位元組的序號
- 16 位元的 接收視窗(Receive window)欄位。用於指示接收方願意接收的位元組數量。
- 4 位元的 首部長度(header length)欄位。指示了以 32 位元的字為單位的 TCP 首部長度。
- 可變與變長的 選項(options)欄位。用於傳送方與接收方協商最大報文段長度時,或在高速網路環境下作用視窗調節因子時使用。
- 6 位元的 標誌(flag)欄位。
- ACK 是對成功接收一個報文段的確認。
- RST、SYN 和 FIN 用於連線的建立和拆除。
- PSH 被設定時,指示接收方應立即將資料交給上層。
- URG 位元用來指示報文段裡存在著被髮送端上層實體置為“緊急”的資料。緊急的最後一個位元組由 16 位元的 緊急資料指標(Urgent data pointer)欄位 指出。
- 注:在實踐中,PSH 、URG 和 緊急資料指標 並不 使用。
3.5.3 往返時間的估計與超時
估計往返時間
- 報文段的樣本RTT:SampleRTT
- SampleRTT 均值:EstimatedRTT
EstimatedRTT=0.875∗EstimeatedRTT+0.125∗SampleRTT
設定和管理超時重傳時間
TimeoutInterval=EstimatedRTT+4∗DevRTT
3.5.4 可靠資料傳輸
- 在 rdt 3.0 中,假定每一個已傳送但未確認的報文段都與一個定時器相關聯。這在理論上是最簡單的,但是維護定時器需要相當大的開銷。所以一般只使用 單一 的重傳定時器。
- 下圖是簡化的 TCP 傳送方:
TCP 傳送方有三個與傳送和重傳有關的事件:
- 從上層應用程式接收資料
- 定時器
- 收到 ACK
超時間隔加倍
當超時事件發生時,每次 TCP 重傳時都會講下一次的超時時間間隔設為先前值的兩倍,直到其他兩個事件發生時,TimeoutInterval 的時間才會由最近的 EstimatedRTT 和 DevRTT 推算得到。快速重傳
- 超時重傳存在的問題是超時的週期較長,會增加端到端時延。
- 但是,傳送方可以在超時事件發生之前通過 冗餘 ACK 來較好的檢測丟包情況。
- 下表是 TCP 接收方的 ACK 接收策略:
事件 | TCP 接收方動作 |
---|---|
具有所期望的序號的按序報文到達。所有在期望序號以及之前的資料都已被確認 | 延遲的 ACK。對另一個按序報文段的到達最多等待 500ms。如果下一個按序報文段在這個時間間隔內沒有到達,則傳送一個 ACK |
具有所期望的序號的按序報文到達。另一個按序報文段等待 ACK 傳輸 | 立即傳送單個累積 ACK,以確認兩個按序報文段 |
比期望序號大的時序報文到達。檢測出間隔 | 立即傳送冗餘 ACK,指示下一個期待位元組的序號(其為間隔的低端的序號) |
能部分或完全填充接收資料間隔的報文段到達 | 倘若該報文段起始於間隔的低端,則立即傳送 ACK |