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)
創建一個 UDP 套接字時,系統會自動爲該套接字分配一個未被其他 UDP 套接字使用的端口號。
也可以用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 |