UDP協(xié)議的那點事兒
UDP( User Datagram Protocol )協(xié)議,翻譯過來就是用戶數(shù)據(jù)報協(xié)議 ,跟 TCP 協(xié)議一樣,都是位于 OSI 模型的傳輸層。不過比起 TCP 協(xié)議,UDP 協(xié)議就顯得簡單多了,因為它沒有「流量控制」、「擁塞控制」等復雜的處理機制。它甚至沒有重傳機制,也就是說,如果你的數(shù)據(jù)包半路走丟了,那就是真找不回來了,所以說 UDP 協(xié)議是不可靠的。當然了,這個重傳機制是針對傳輸層而言的,你完全可以在應用層寫一個協(xié)議來進行丟包處理,比如說像 TCP 一樣,增加 ACK 和序列號機制。
那你可能會疑惑了,為什么放著可靠的 TCP 協(xié)議不用,而選擇 UDP 協(xié)議?
UDP 報文段結(jié)構(gòu)
這當然要根據(jù)應用的需求來,不過在說這個話題之前,我們先來詳細了解一下 UDP 協(xié)議。
說實話,UDP 的報文段結(jié)構(gòu)比 TCP 報文段簡潔多了(見下圖),畢竟 UDP 協(xié)議就沒有什么多余的機制。
言歸正傳,報文段里的「源端口號」和「目的端口號」是為了告訴傳輸層,我這個報文是從哪兒(哪個進程)來的,要到哪兒(哪個進程)去。但要注意一點:一個 UDP 套接字是由一個二元組標識的,這個二元組指的是目的 IP 地址和目的端口號,也就是說,服務器上對應的進程,不在乎你是從哪個客戶端來的,我都放進同一個套接字處理,處理完了再根據(jù)源端口號和源 IP 地址,把應答信息發(fā)送給客戶端。相較而言,TCP 套接字需要一個四元組來標識:源 IP 地址,源端口號,目的 IP 地址和目的端口號。這一點在講 TCP 協(xié)議的時候還會細講,所以這里就不贅述了。
PS:你可能會問,這報文段里怎么沒有 IP 地址啊?這是因為IP 地址保存在網(wǎng)絡層的 IP 協(xié)議段里,傳輸層的報文段里當然就沒有了。
無連接
每次提到 TCP 協(xié)議,我們最先想到的就是三次握手和四次揮手,對 UDP 協(xié)議來說,這都是沒有的事兒~ 使用 UDP 協(xié)議的時候,如果客戶端要發(fā)送報文段給服務端,不用握手,直接就發(fā)出去了,也正因為這樣,UDP 協(xié)議被稱為是無連接的。
很容易想到,不需要握手這一過程的話,就沒有因為建立連接而造成的時延,一個字,快!這也是 DNS(域名系統(tǒng))運行在 UDP 協(xié)議之上的很大一部分原因。
但是 UDP 協(xié)議不可靠啊,傳輸過程中丟包了怎么辦?最簡單的做法就是——忽略它!(否則就得像文章開頭說的那樣,在應用層實現(xiàn)重傳機制)就拿 DNS 來說吧,如果數(shù)據(jù)包丟失,客戶端重發(fā)就是了(有超時機制),而且在正常情況下,丟包的概率很低。但如果使用 TCP 協(xié)議的話,因為要建立連接,域名查詢就會慢很多,除此之外,使用 UDP 協(xié)議的網(wǎng)絡開銷更小——UDP 報文段有 8 個字節(jié)的首部開銷,而 TCP 協(xié)議有 20 字節(jié)的開銷(看前面的關(guān)于報文段的兩張圖)。網(wǎng)絡開銷小,意味著 DNS 服務器能接受更多客戶端的請求。
還有一個方面,TCP 協(xié)議有擁塞控制機制,它會在網(wǎng)絡擁塞時遏制 TCP 發(fā)送方,以至于延遲報文段的傳送,所以對于一些要求傳輸延遲小,且能夠容忍一些數(shù)據(jù)丟失的實時程序來說,UDP 協(xié)議可能是一個更好的選擇。路由選擇協(xié)議(RIP)、 網(wǎng)絡管理協(xié)議(SNMP) 也都選擇了 UDP 來作為底層的傳輸協(xié)議。
最后,這是一張客戶端與服務端利用 UDP 協(xié)議通信的流程圖:
UDP 協(xié)議要講的內(nèi)容不多,下次要講的 TCP 協(xié)議,就比較燒腦了,做好準備吧!