# Computer Networking — 3.3 Connectionless Transport: UDP contributed by <[`kaeteyaruyo`](https://github.com/kaeteyaruyo)> ###### tags: `Computer Networking` 在本節中,我們將會探索 UDP 的方方面面,了解他的運作機制,認識他的工作內容。我們推薦你同時參照著 [2.1](https://hackmd.io/@kaeteyaruyo/computer-networking-2-1) 節一起看,當時我們有簡單介紹了 UDP 的服務模型,還有 [2.7.1](https://hackmd.io/@kaeteyaruyo/computer-networking-2-7#271-Socket-Programming-with-UDP) 小節也可以參考,當時我們探討了如何實作 UDP 的 socket 程式。 為了引發我們對 UDP 的討論,先假設你有興趣設計一個簡單的傳輸通訊協定。你應該怎麼做呢?首先,你可以考慮使用一個啥都不做的傳輸通訊協定。特別是在傳送端,你可能會考慮從應用程式行程直接將訊息傳送到網路層;而在接收端,你可能會考慮從網路層傳送訊息到應用程式行程。但是,正如我們在上一節所學到的,我們得要比啥都沒做還要多做一些事情!至少,傳輸層必須提供多工/解多工服務,以便在網路層和正確的應用程式層行程之間傳遞資料。 UDP 定義於 [RFC 768],作為一個傳輸協定,他會做的事情真是不能再更少了。除了多工/解多工功能和一些輕微的錯誤檢查之外,他沒有在 IP 之上加任何東西。事實上,如果應用程式開發者選擇 UDP 而非 TCP,那麼應用程式幾乎可以直接與 IP 溝通。UDP 從應用程式行程中取得訊息,附加多工/解多工服務的來源和目的地埠號欄位,再加上另外兩個小欄位,然後將產生的區段 (segment) 傳送到網路層。網路層將傳輸層區段封裝成 IP 資料塊 (datagram),然後盡最大努力將區段傳送到接收主機。如果區段到達接收端主機,UDP 會使用目的埠號將區段資料傳送到正確的應用程式行程。請注意,使用 UDP 時,在傳送區段之前傳送層實體與接收層實體之間並不會進行交握(handshaking)。因此,我們稱 UDP 是*無連接式的 (connectionless)*。 DNS 是一個典型的使用 UDP 的應用層通訊協定範例。當主機中的 DNS 應用程式要進行查詢時,它會建構一個 DNS 查詢訊息,並將訊息傳送給 UDP。主機端 UDP 不會與目的地系統上執行的 UDP 實體進行任何交握,他就只是將訊息的標頭欄位加入到訊息中,然後將結果區段直接傳送到網路層。網路層會將 UDP 區段封裝成資料塊,並將資料塊傳送至域名伺服器。送出查詢的主機上的 DNS 應用程式會等待查詢回覆。如果沒有收到回覆(可能是因為底層網路把查詢或回覆弄丟了),它可能會嘗試重新傳送查詢、嘗試將查詢傳送至另一個名稱伺服器,或通知執行查詢的應用程式它無法收到回覆。 現在你可能會想,為什麼應用程式開發人員會選擇在 UDP 上建立應用程式,而不是在 TCP 上呢?TCP 會提供可靠的資料傳輸服務,而 UDP 則不會,這樣 TCP 不是應該比較好嗎?答案是否定的,因為某些應用程式較適合使用 UDP,原因如下: * **對於何時傳送何種資料,有更精細的應用程式層級控制**:在 UDP 下,只要應用程式行程將資料傳送到 UDP,UDP 就會將資料包裝在 UDP 區段內,並立刻將區段傳送到網路層。另一方面,TCP 具有擁塞控制機制,當來源主機和目的地主機之間的一條或多條連結過度擁塞時,TCP 會對傳輸層傳送者進行節流。TCP 也會持續重新傳送一個區段,直到目的地確認收到該區段為止,不論可靠傳送所需的時間有多長。由於即時應用程式通常需要最低的傳送速率、不希望過度延遲區段傳輸,而且可以容忍某些資料遺失,因此 TCP 的服務模型並沒有那麼適合這些應用程式。如下所述,這些應用程式可以使用 UDP,然後再額外實作那些 UDP 陽春的區段傳輸服務所沒有提供的所需的附加功能(作為應用程式的一部份)。 * **無連線建立**:正如我們稍後會討論到的,TCP 在開始傳輸資料前會先進行三方交握。而 UDP 只會直接傳送資料,不需要任何正式的前置動作。因此,UDP 在建立連線時不會有任何延遲。這可能是 DNS 透過 UDP 而非 TCP 執行的主要原因 —— 如果 DNS 透過 TCP 執行,速度會慢很多。HTTP 使用 TCP 而不是 UDP,是因為可靠性對有文字的網頁來說是很重要的。但是,正如我們在 2.2 節所簡要討論的,HTTP 的 TCP 連線建立延遲是造成下載網頁文件延遲的重要原因。事實上,Google Chrome 瀏覽器所使用的 QUIC 協定 (Quick UDP Internet Connection, [Iyengar 2015]) 就是使用 UDP 作為其底層傳輸協定,並在 UDP 的應用層協定上實現可靠性。 * **無連線狀態**:TCP 會在終端系統上維持連線狀態。此連線狀態包括接收和傳送緩衝區、擁塞控制參數,以及順序和確認號碼參數。在 [3.5](https://hackmd.io/@kaeteyaruyo/computer-networking-3-5) 節中,我們將會看到這些狀態資訊是執行 TCP 可靠資料傳輸服務和提供擁塞控制所必需的。另一方面,UDP 不維護連線狀態,也不追蹤任何這些參數。因此,當應用程式透過 UDP 而非 TCP 執行時,專門用於特定應用程式的伺服器通常可以支援更多的客戶端進行傳輸。 * **封包標頭開銷小**:TCP 每段有 20 位元組的封頭開銷,而 UDP 只有 8 位元組的開銷。  > Figure 3.6 一些知名的網際網路應用服務以及其所使用的傳輸協定 Figure 3.6 列出了常用的網際網路應用服務及其所使用的傳輸通訊協定。正如我們所預期的,電子郵件、遠端終端存取、網頁和檔案傳輸都是透過 TCP 執行,所有這些應用程式都需要 TCP 可靠的資料傳輸服務。儘管如此,還是有許多重要的應用程式是在 UDP 而非 TCP 之上執行的。例如,UDP 用於傳輸網路管理資料(SNMP; 請參閱 [5.7](https://hackmd.io/@kaeteyaruyo/computer-networking-5-7) 節)。在這種情況下,UDP 比 TCP 更為適用,因為網路管理應用程式通常是在網路處於緊張狀態時執行,也就是可靠、擁擠受控的資料傳輸難以實現的時候。此外,正如我們之前提到的,DNS 執行在 UDP 之上,因此避免了 TCP 的連線建立延遲。 如 Figure 3.6 所示,現今 UDP 和 TCP 有時都會用於多媒體應用程式,例如網路電話、即時視訊會議,以及儲存的音訊和視訊串流。我們將在第 9 章詳細介紹這些應用程式。我們現在只想提一下,所有這些應用程式都可以容忍少量的封包遺失,因此可靠的資料傳輸對應用程式的執行並非絕對重要。此外,即時應用程式(如網路電話和視訊會議)==對 TCP 擁塞控制的反應非常差(啥意思)==。基於這些原因,多媒體應用程式的開發者有可能會選擇在 UDP 而非 TCP 上執行應用程式。當封包丟失率很低時,加上有些組織基於安全理由封鎖 UDP 流量(請參閱第 8 章),TCP 對於串流媒體傳輸而言,變得越來越有吸引力。 儘管現在普遍使用 UDP,但在 UDP 上執行多媒體應用程式仍有爭議。如上文所述,UDP 沒有擁塞控制機制。但擁塞控制是需要的,以防止網路進入擁塞狀態,在此狀態下網路幾乎無法完成任何有用的事情。如果每個人都不使用任何擁塞控制就開始串流高位元率的視訊,路由器就會出現大量的封包溢位,只有極少數的 UDP 封包能成功穿越來源到目的地的路徑。此外,不受控制的 UDP 傳輸方所造成的高遺失率,會導致 TCP 傳輸方(我們等等就會看到,這些傳輸方在面對擁塞時*真的會*降低其傳送率)大幅降低其傳送率。因此,UDP 中缺乏擁塞控制會導致 UDP 傳輸方和接收方之間的高封包遺失率,以及 TCP session 的壅塞 —— 這是一個潛在的嚴重問題 [Floyd 1999]。許多研究人員已提出新的機制,強制所有來源(包括 UDP 來源)執行適應性的擁塞控制 [Mahdavi 1997; Floyd 2000; Kohler 2006: RFC 4340]。 在討論 UDP 區段結構之前,我們想先提到應用程式其實*是有可能*透過 UDP 獲得可靠的資料傳輸的。如果將可靠度內建到應用程式本身(例如,加入確認和重傳機制,像是我們將在下一節研究的那種機制),就可以做到這一點。我們之前有提到 Google Chrome 瀏覽器所使用的 QUIC 通訊協定 [Iyengar 2015],就有在 UDP 之上的應用層通訊協定中實作可靠性。但這是一項不容易的任務,會讓應用程式開發人員花很長時間忙於除錯。儘管如此,直接在應用程式中建立可靠性,可以讓應用程式「魚與熊掌得以兼得」。也就是說,應用程式行程可以可靠地進行通訊,又無需受到 TCP 壅塞控制機制所施加的傳輸速率限制。 ## 3.3.1 UDP Segment Structure  > Figure 3.7 UDP 區段結構 UDP 區段結構(如 Figure 3.7 所示)是在 RFC 768 中定義的。應用程式資料佔用 UDP 區段的資料欄位。例如,以 DNS 來說,資料欄位包含查詢訊息或回應訊息。對於串流音訊應用程式,音訊樣本會填滿資料欄位。UDP 標頭只有四個欄位,每個由兩個位元組所組成。如上一節所述,埠號可以讓目的地主機將應用程式資料傳送至在目的地系統上執行的正確行程(即執行解多工功能)。長度欄位指定 UDP 區段(標頭 + 資料)的位元組數量。由於每個 UDP 段的資料欄位大小可能不同,因此需要明確的長度值。接收方主機使用校驗和來檢查區段中是否有錯誤。事實上,除了 UDP 區段之外,校驗和也是根據 IP 標頭中的幾個欄位來計算的,但我們忽略這個細節,以便綜覽全局。我們將在下面討論校驗和計算。錯誤偵測的基本原則將在 [6.2](https://hackmd.io/@kaeteyaruyo/computer-networking-6-2) 節中說明。<span style="color: #AAA">長度欄位說明了 UDP 區段包含其標頭的長度,以位元組為單位。(譯註:後面這句話應該是重複的,可能再版時沒刪掉)</span> ## 3.3.2 UDP Checksum UDP 校驗和負責用來做錯誤偵測。也就是說,校驗和用來判斷 UDP 區段內的位元在從來源移動到目的地的過程中是否被改變過(例如,因鏈路中的雜訊被改變,或是存放在路由器中時被改變)。UDP 會在傳送端對區段中所有 16-bit word 的總和進行一補數運算,總和過程中遇到的任何溢位都會被 wrapped around(譯註:即將最高位的進位循環加回最低位去)。這個結果會被放在 UDP 區段的校驗和欄位中。我們在這裡舉一個簡單的校驗和計算範例。你可以在 RFC 1071 中找到更高效的實作的詳細資訊,也可以在 [Stone 1998; Stone 2000] 中找到該實作在真實資料上的執行效能。舉例來說,假設我們有以下三個 16-bit word: ``` 0110011001100000 0101010101010101 1000111100001100 ``` 前兩個 16-bit word 的總和為: ``` 0110011001100000 0101010101010101 ---------------- 1011101110110101 ``` 將第三個字加上上面的總和,得到: ``` 1011101110110101 1000111100001100 ---------------- 0100101011000010 ``` 注意最後這個加法有溢位且被 wrapped around 了。接著將所有的 0 轉換成 1,將所有的 1 轉換成 0,就得到其一補數。因此總和 `0100101011000010` 的一補數是 `1011010100111101`,而這會被當成校驗和。在接收方,所有四個 16-bit word 都會被相加,包括校驗和。如果封包中沒有引入錯誤,那麼接收器的總和顯然是 `1111111111111111`。如果其中一個位元是 0,那麼我們就知道封包中出現了錯誤。 你可能會疑惑,既然許多連結層通訊協定(包括流行的乙太網路通訊協定)也提供錯誤檢查,為什麼 UDP 還要先提供校驗和呢?這是因為我們無法保證來源與目的地之間的所有的連結都有提供錯誤檢查;也就是說,其中一個連結可能使用不提供錯誤檢查的連結層通訊協定。此外,即便區段在連結間正確傳輸,當區段儲存在路由器的記憶體中時,也有可能發生位元錯誤。鑑於無論是逐條連結的可靠性或記憶體內的錯誤偵測都無法保證,因此,如果端到端的資料傳輸服務要提供錯誤偵測,UDP 就必須在傳輸層上*端到端地*進行錯誤偵測。這是系統設計中著名的**端到端原則 (end-end principle)** [Saltzer 1984] 的一個例子,該原則指出,由於某些功能(在本例中為錯誤偵測)必須在端到端基礎上實作:「與在較高層級提供這些功能的成本相比,在較低層級實作這些功能可能是冗贅的或價值不大」。 因為 IP 照理來說可以在任何第二層通訊協定之上執行,所以傳輸層提供錯誤檢查作為安全措施是很有用的。雖然 UDP 提供錯誤檢查,但它不會做任何事情來從錯誤中恢復。有些 UDP 實作只是丟棄損壞的區段,有些則將損壞的區段傳給應用程式並加上警告。 我們對 UDP 的討論到此為止。我們很快就會看到 TCP 為其應用程式提供可靠的資料傳輸,以及 UDP 沒有提供的其他服務。當然,TCP 也比 UDP 複雜。然而,在討論 TCP 之前,我們應該先回過頭來討論可靠資料傳輸的基本原則。 ---- [<< 3.2 Multiplexing and Demultiplexing](https://hackmd.io/@kaeteyaruyo/computer-networking-3-2) | [目錄](https://hackmd.io/@kaeteyaruyo/computer-networking-index) | [3.4 Principles of Reliable Data Transfer >>](https://hackmd.io/@kaeteyaruyo/computer-networking-3-4)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up