0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

UDP分片與丟包,UDP真的比TCP高效嗎?

馬哥Linux運(yùn)維 ? 來(lái)源:馬哥Linux運(yùn)維 ? 作者:馬哥Linux運(yùn)維 ? 2022-12-21 11:12 ? 次閱讀

一、UDP 報(bào)文格式

每個(gè) UDP 報(bào)文分為 UDP 報(bào)頭和 UDP 數(shù)據(jù)區(qū)兩部分。報(bào)頭由 4 個(gè) 16 位長(zhǎng)(2 字節(jié))字段組成,分別說(shuō)明該報(bào)文的源端口、目的端口、報(bào)文長(zhǎng)度和校驗(yàn)值。

UDP 報(bào)文格式如圖所示。

75a523ba-806a-11ed-8abf-dac502259ad0.png

UDP 報(bào)文中每個(gè)字段的含義如下:

  • 源端口:16bits,發(fā)送端的端口。
  • 目的端口:16bits,即接收端的端口
  • 長(zhǎng)度:16bits,UDP 數(shù)據(jù)包總的大?。喊^+數(shù)據(jù),單位:字節(jié)。
  • 校驗(yàn)值:16bits,錯(cuò)誤檢查碼,基于算法,計(jì)算此 UDP 數(shù)據(jù)包是否損壞

二、UDP 分片

1、UDP 有發(fā)送緩存區(qū)嗎?

TCP 有 發(fā)送/接收 緩存區(qū),那 UDP 有么?

1>、先說(shuō)結(jié)論:

每個(gè) UDP socket 都有一個(gè)接收緩沖區(qū),沒(méi)有發(fā)送緩沖區(qū),從概念上來(lái)說(shuō)就是只要有數(shù)據(jù)就發(fā),不管對(duì)方是否可以正確接收,所以不緩沖,不需要發(fā)送緩沖區(qū)。

UDP:當(dāng)套接口接收緩沖區(qū)滿時(shí),新來(lái)的數(shù)據(jù)報(bào)無(wú)法進(jìn)入接收緩沖區(qū),此數(shù)據(jù)報(bào)就被丟棄。UDP是沒(méi)有流量控制的;快的發(fā)送者可以很容易地就淹沒(méi)慢的接收者,導(dǎo)致接收方的 UDP 丟棄數(shù)據(jù)報(bào)。

且,如果在傳輸過(guò)程中,一次傳輸被分成多個(gè)分片,傳輸中有一個(gè)小分片丟失,那接收端最終會(huì)舍棄整個(gè)文件,導(dǎo)致傳輸失敗,這就是 UDP 不可靠的原因。

2>、逐步分析:

linux手冊(cè)中有設(shè)置 UDP 發(fā)送緩沖區(qū)相關(guān)屬性,也明確提到了send buffer的概念:

75c4b914-806a-11ed-8abf-dac502259ad0.png

那這是否意味著 UDP 是有發(fā)送緩沖區(qū)的嗎?我們?cè)倏匆幌隆禪NIX Network Programming》書(shū)中所述,這本書(shū)的作者權(quán)威性我就不多說(shuō)了吧,在國(guó)內(nèi)高校此書(shū)都是當(dāng)做教材使用的。書(shū)中有下面兩幅圖:

75ecfc80-806a-11ed-8abf-dac502259ad0.png

7618902a-806a-11ed-8abf-dac502259ad0.png

一張是 TCP 發(fā)送過(guò)程協(xié)議棧簡(jiǎn)化圖,另一張是 UDP 的。UDP 中的 send buffer 是用虛線框圈起來(lái)的,具體的敘述我直接引用書(shū)中原文:

764bd8a4-806a-11ed-8abf-dac502259ad0.png

書(shū)中的描述很清楚了,UDP 是沒(méi)有發(fā)送緩沖區(qū)的,因?yàn)?UDP 是不可靠的,他不必像 TCP 一樣需要一個(gè)實(shí)質(zhì)的發(fā)送buffer,而且真正 UDP 寫成功返回其實(shí)是傳遞到了鏈路層的 output queue 中。

2、UDP 分片

1>、UDP 包最佳傳輸大小

數(shù)據(jù)鏈路層 最大傳輸單元是 1500 字節(jié) (MTU) ,要想 IP 層不分包,那么 UDP 數(shù)據(jù)包的最大大小應(yīng)該是1500字節(jié) – IP頭(20字節(jié)) – UDP頭(8字節(jié)) = 1472字節(jié)。

但,理論上 UDP 報(bào)文最大長(zhǎng)度是 65507 字節(jié),那:實(shí)際上發(fā)送這么大的數(shù)據(jù)包效果最好嗎?

我們來(lái)看分析一下 “分片問(wèn)題”

2>、分片問(wèn)題

我們知道 UDP 是不可靠的傳輸協(xié)議,為了減少 UDP 包丟失的風(fēng)險(xiǎn),我們最好能控制 UDP 包在 IP層協(xié)議的傳輸過(guò)程中不要被切割。

這是為什么呢?

如果 MTU 是1500,Client 發(fā)送一個(gè) 8000字節(jié)大小的 UDP 包,那么 Server 端阻塞模式下接包,在不丟包的情況下,recvfrom(9000) 是收到 1500,還是 8000。如果某個(gè) IP 分片丟失了,recvfrom(9000),又返回什么呢?

根據(jù) UDP 通信的有界性,在 buf 足夠大的情況下,接收到的一定是一個(gè)完整的數(shù)據(jù)包,UDP 數(shù)據(jù)在下層的分片和組片問(wèn)題由 IP 層來(lái)處理,提交到 UDP 傳輸層一定是一個(gè)完整的 UDP 包,那么 recvfrom(9000) 將返回 8000。如果某個(gè) IP 分片丟失,udp 里有個(gè) CRC 檢驗(yàn),如果包不完整就會(huì)丟棄,也不會(huì)通知是否接收成功,所以 UDP 是不可靠的傳輸協(xié)議,那么 recvfrom(9000) 將阻塞。

分片分的越多,雖然在傳輸層都是一次 send,一次 recv ,但在傳輸過(guò)程中,會(huì)傳輸多次,那么丟包的概論就越大,如何解決丟包問(wèn)題呢?

三、UDP 丟包的原因

前提:

在不考慮 IP 層的分片丟失,CRC 檢驗(yàn)包不完整的情況下

1、UDP 緩沖區(qū)滿,造成的丟包

如果 socket緩沖區(qū)滿了,應(yīng)用程序沒(méi)來(lái)得及處理在緩沖區(qū)中的 UDP 包,那么后續(xù)來(lái)的 UDP 包會(huì)被內(nèi)核丟棄,造成丟包。

在 socket 緩沖區(qū)滿造成丟包的情況下,可以通過(guò)增大緩沖區(qū)的方法來(lái)緩解UDP丟包問(wèn)題。但是,如果服務(wù)已經(jīng)過(guò)載了,簡(jiǎn)單的增大緩沖區(qū)并不能解決問(wèn)題,反而會(huì)造成滾雪球效應(yīng),造成請(qǐng)求全部超時(shí),服務(wù)不可用。

2、UDP 緩沖區(qū)過(guò)小或文件過(guò)大,造成的丟包:

如 果Client 發(fā)送的 UDP 報(bào)文很大,而 socket 緩沖區(qū)過(guò)小無(wú)法容下該 UDP 報(bào)文,那么該報(bào)文就會(huì)丟失。

以前遇到過(guò)這種問(wèn)題,我把接收緩沖設(shè)置成 64K 就解決了。

int nRecvBuf=32*1024;//設(shè)置為32K

setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));

3、ARP 緩存過(guò)期,導(dǎo)致丟包:

ARP 的緩存時(shí)間約 10 分鐘,APR 緩存列表沒(méi)有對(duì)方的 MAC 地址或緩存過(guò)期的時(shí)候,會(huì)發(fā)送 ARP 請(qǐng)求獲取 MAC 地址,

在沒(méi)有獲取到 MAC 地址之前,用戶發(fā)送出去的 UDP 數(shù)據(jù)包會(huì)被內(nèi)核緩存到 arp_queue 這個(gè)隊(duì)列中,默認(rèn)最多緩存 3 個(gè)包,多余的 UDP 包會(huì)被丟棄。

4、接收端處理時(shí)間過(guò)長(zhǎng)導(dǎo)致丟包:

調(diào)用 recv 方法接收端收到數(shù)據(jù)后,處理數(shù)據(jù)花了一些時(shí)間,處理完后再次調(diào)用 recv 方法,在這二次調(diào)用間隔里,發(fā)過(guò)來(lái)的包可能丟失。

對(duì)于這種情況可以修改接收端,將包接收后存入一個(gè)緩沖區(qū),然后迅速返回繼續(xù) recv。

5、發(fā)送的包巨大丟包:

雖然 send 方法會(huì)幫你做大包切割成小包發(fā)送的事情,但包太大也不行。

例如超過(guò) 50K 的一個(gè) udp 包,不切割直接通過(guò)send 方法發(fā)送也會(huì)導(dǎo)致這個(gè)包丟失。這種情況需要切割成小包再逐個(gè) send。

6、發(fā)送的包頻率太快:

雖然每個(gè)包的大小都小于 mtu size 但是頻率太快,例如 40 多個(gè) mut size 的包連續(xù)發(fā)送中間不 sleep,也有可能導(dǎo)致丟包。

這種情況也有時(shí)可以通過(guò)設(shè)置 socket 接收緩沖解決,但有時(shí)解決不了。

所以在發(fā)送頻率過(guò)快的時(shí)候還是考慮 sleep一下吧。

7、局域網(wǎng)內(nèi)不丟包,公網(wǎng)上丟包。

這個(gè)問(wèn)題我也是通過(guò)切割小包并 sleep發(fā)送解決的。如果流量太大,這個(gè)辦法也不靈了。

總之 udp 丟包總是會(huì)有的,如果出現(xiàn)了用我的方法解決不了,還有這個(gè)幾個(gè)方法:要么減小流量,要么換 tcp 協(xié)議傳輸,要么做丟包重傳的工作。

四、UDP 丟包的解決方案

1. 從發(fā)送端解決 - 延遲發(fā)送

適用條件:

發(fā)送端是可以控制的.

微秒數(shù)量級(jí)的延遲可以接受.

解決方法:

發(fā)送時(shí)使用 usleep(1) 延遲 1 微秒發(fā)送,即發(fā)送頻率不要過(guò)快

延遲1微妙發(fā)送,可以很好的解決這個(gè)問(wèn)題.

2.從接收端解決:數(shù)據(jù)接收 與 數(shù)據(jù)處理相分離

適用條件:

無(wú)法控制發(fā)送端發(fā)送數(shù)據(jù)的頻率

解決方法:

用 recvfrom 函數(shù)收到數(shù)據(jù)之后盡快返回,進(jìn)行下一次 recvfrom,可以通過(guò) 多線程+隊(duì)列 來(lái)解決。

收到數(shù)據(jù)之后將數(shù)據(jù)放入隊(duì)列中,另起一個(gè)線程去處理收到的數(shù)據(jù).

3.從接收端解決:修改接收緩存大小 適用條件:

使用方法 2 依然出現(xiàn)大規(guī)模丟包的情況,需要進(jìn)一步優(yōu)化

解決方法:

使用 setsockopt 修改接收端的緩沖區(qū)大小

intrcv_size=1024*1024;//1M
intoptlen=sizeof(rcv_size);
//設(shè)置好緩沖區(qū)大小
interr=setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&rcv_size,optlen);

設(shè)置完畢可以通過(guò)下列函數(shù),來(lái)查看當(dāng)前 sock 的緩沖區(qū)大小

setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&rcv_size,(socklen_t*)&optlen);

但是,會(huì)發(fā)現(xiàn)查到的大小并不是1M而是256kb,后來(lái)發(fā)現(xiàn)原來(lái)是 linux 系統(tǒng)默認(rèn)緩沖區(qū)大小為 128kb,設(shè)置最大是這個(gè)的 2倍,所以需要通過(guò)修改系統(tǒng)默認(rèn)緩沖區(qū)大小來(lái)解決

使用root賬戶在命令行下輸入:

vi/etc/sysctl.conf

添加一行記錄(1049576=1024*1024=1M)

net.core.rmem_max=1048576

保存之后輸入

/sbin/sysctl-p

使修改的配置生效

此時(shí)可以通過(guò) sysctl -a|grep rmem_max 來(lái)看配置是否生效.

生效之后可以再次運(yùn)行程序來(lái) getsockopt 看緩沖區(qū)是否變大了,是否還會(huì)出現(xiàn)丟包現(xiàn)象了

樓主使用的是 方法2+方法3 雙管齊下,已經(jīng)不會(huì)出現(xiàn)丟包現(xiàn)象了,如果還有不同程度的丟包 可以通過(guò)方法三種繼續(xù)增加緩沖區(qū)大小的方式來(lái)解決。

五、UDP 實(shí)現(xiàn)對(duì)方百分百收到數(shù)據(jù)

1、UDP 致命性缺點(diǎn):

UDP 是無(wú)連接的,面向消息的數(shù)據(jù)傳輸協(xié)議,與TCP相比,有兩個(gè)致命的缺點(diǎn)

一是:數(shù)據(jù)包容易丟失

二是:數(shù)據(jù)包無(wú)序

2、解決方案 - 回復(fù) + 重發(fā) + 編號(hào) 機(jī)制:

1>、分析:

要實(shí)現(xiàn)文件的可靠傳輸,就必須在上層對(duì)數(shù)據(jù)丟包和亂序作特殊處理,必須要有要有丟包重發(fā)機(jī)制和超時(shí)機(jī)制。

常見(jiàn)的可靠傳輸算法有模擬 TCP協(xié)議,重發(fā)請(qǐng)求(ARQ)協(xié)議,它又可分為連續(xù)ARQ協(xié)議、選擇重發(fā)ARQ協(xié)議、滑動(dòng)窗口協(xié)議等等。

如果只是小規(guī)模程序,也可以自己實(shí)現(xiàn)丟包處理,原理基本上就是給文件分塊,每個(gè)數(shù)據(jù)包的頭部添加一個(gè)唯一標(biāo)識(shí)序號(hào)的 ID 值,當(dāng)接收的包頭部 ID 不是期望中的 ID 號(hào),則判定丟包,將丟包 ID 發(fā)回服務(wù)端,服務(wù)器端接到丟包響應(yīng)則重發(fā)丟失的數(shù)據(jù)包。

模擬 TCP 協(xié)議也相對(duì)簡(jiǎn)單,3次握手的思想對(duì)丟包處理很有幫助

2>、回復(fù) + 重發(fā) + 編號(hào) 機(jī)制

1)接收方收到數(shù)據(jù)后,回復(fù)一個(gè)確認(rèn)包

如果你不回復(fù),那么發(fā)送端是不會(huì)知道接收方是否成功收到數(shù)據(jù)的。

比如:A 要發(fā)數(shù)據(jù) “{data}” 到 B,那 B 收到后,可以回復(fù)一個(gè)特定的確認(rèn)包 “{OK}”,表示成功收到。

但是如果只做上面的回復(fù)處理,還是有問(wèn)題:

比如 B 收到數(shù)據(jù)后回復(fù)給 A 的數(shù)據(jù) "{OK}" 的包,A 沒(méi)收到,怎么辦呢???

2)當(dāng) A 沒(méi)有收到B的 "{OK}" 包后,要做定時(shí)重發(fā)數(shù)據(jù)

定時(shí)重發(fā),直到成功接收到確認(rèn)包為止,再發(fā)下面的數(shù)據(jù),當(dāng)然,重發(fā)了一定數(shù)量后還是沒(méi)能收到確認(rèn)包,可以執(zhí)行一下 ARP 的流程,防止對(duì)方網(wǎng)卡更換或別的原因。

但是這樣的話,B 會(huì)收到很多重復(fù)的數(shù)據(jù),假如每次都是 B 回復(fù)確認(rèn)包 A 收不到的話。

3)發(fā)送數(shù)據(jù)的包中加個(gè)標(biāo)識(shí)符 - 編號(hào)

比如 A 要發(fā)送的數(shù)據(jù) “{標(biāo)識(shí)符 | data}”到 B,B 收到后,先回復(fù) “{OK}" 確認(rèn)包,再根據(jù)原有的標(biāo)識(shí)符進(jìn)行比較,如果標(biāo)識(shí)符相同,則數(shù)據(jù)丟失,如果不相同,則原有的標(biāo)識(shí)符 = 接收標(biāo)識(shí)符,且處理數(shù)據(jù)。

當(dāng) A 發(fā)送數(shù)據(jù)包后,沒(méi)有收到確認(rèn)包,則每隔 x 秒,把數(shù)據(jù)重發(fā)一次,直到收到確認(rèn)包后,更新一下標(biāo)識(shí)符,再進(jìn)行后一包的數(shù)據(jù)發(fā)送。

經(jīng)過(guò)上面1),2),3)點(diǎn)的做法,則可以保證數(shù)據(jù)百分百到達(dá)對(duì)方,當(dāng)然,標(biāo)識(shí)符用 ID 號(hào)來(lái)代替更好。

3、解決方案 - 冗余傳輸方案:

在外網(wǎng)通信鏈路不穩(wěn)定的情況下,有什么辦法可以降低UDP的丟包率呢?

一個(gè)簡(jiǎn)單的辦法來(lái)采用冗余傳輸?shù)姆绞健?/p>

如下圖,一般采用較多的是延時(shí)雙發(fā),雙發(fā)指的是將原本單發(fā)的前后連續(xù)的兩個(gè)包合并成一個(gè)大包發(fā)送,這樣發(fā)送的數(shù)據(jù)量是原來(lái)的兩倍。

這種方式提高丟包率的原理比較簡(jiǎn)單,例如本例的冗余發(fā)包方式,在偶數(shù)包全丟的情況下,依然能夠還原出完整的數(shù)據(jù),也就是在這種情況下,50%的丟包率,依然能夠達(dá)到100%的數(shù)據(jù)接收。

7682cd28-806a-11ed-8abf-dac502259ad0.jpg

4、解決方案 - RUDP:

UDP 實(shí)現(xiàn)可靠性既然那么麻煩,那直接用 TCP 好了!確實(shí)很多人也都是這樣做的,TCP 是個(gè)基于公平性的可靠通信協(xié)議,但是在一些苛刻的網(wǎng)絡(luò)條件下 TCP 要么不能提供正常的通信質(zhì)量保證,要么成本過(guò)高。為什么要在 UDP 之上做可靠保證,究其原因就是在保證通信的時(shí)延和質(zhì)量的條件下盡量降低成本。RUDP 主要解決以下相關(guān)問(wèn)題:

  • 端對(duì)端連通性問(wèn)題:一般終端直接和終端通信都會(huì)涉及到 NAT 穿越,TCP 在 NAT 穿越實(shí)現(xiàn)非常困難,相對(duì)來(lái)說(shuō) UDP 穿越 NAT 卻簡(jiǎn)單很多,如果是端到端的可靠通信一般用 RUDP 方式來(lái)解決,場(chǎng)景有:端到端的文件傳輸、實(shí)時(shí)音視頻傳輸、交互指令傳輸?shù)鹊??!綰DP NAT穿越簡(jiǎn)單很多】

  • 弱網(wǎng)環(huán)境傳輸問(wèn)題:在一些 Wi-Fi 或者 3G/4G 移動(dòng)網(wǎng)下,需要做低延遲可靠通信,如果用 TCP 通信延遲可能會(huì)非常大,這會(huì)影響用戶體驗(yàn)。例如:實(shí)時(shí)的操作類網(wǎng)游通信、語(yǔ)音對(duì)話、多方白板書(shū)寫等,這些場(chǎng)景可以采用特殊的 RUDP 方式來(lái)解決這類問(wèn)題;【弱網(wǎng)傳輸U(kuò)DP延長(zhǎng)會(huì)低很多】

  • 帶寬競(jìng)爭(zhēng)問(wèn)題:有時(shí)候客戶端數(shù)據(jù)上傳需要突破本身 TCP 公平性的限制來(lái)達(dá)到高速低延時(shí)和穩(wěn)定,也就是說(shuō)要用特殊的流控算法來(lái)壓榨客戶端上傳帶寬,例如:直播音視頻推流,這類場(chǎng)景用 RUDP 來(lái)實(shí)現(xiàn)不僅能壓榨帶寬,也能更好地增加通信的穩(wěn)定性,避免類似 TCP 的頻繁斷開(kāi)重連;

  • 傳輸路徑優(yōu)化問(wèn)題:在一些對(duì)延時(shí)要求很高的場(chǎng)景下,會(huì)用應(yīng)用層 relay 的方式來(lái)做傳輸路由優(yōu)化,也就是動(dòng)態(tài)智能選路,這時(shí)雙方采用 RUDP 方式來(lái)傳輸,中間的延遲進(jìn)行 relay 選路優(yōu)化延時(shí)。還有一類基于傳輸吞吐量的場(chǎng)景,例如:服務(wù)與服務(wù)之間數(shù)據(jù)分發(fā)、數(shù)據(jù)備份等,這類場(chǎng)景一般會(huì)采用多點(diǎn)并聯(lián) relay 來(lái)提高傳輸?shù)乃俣?,也是要建立?RUDP 上的(這兩點(diǎn)在后面著重來(lái)描述);

  • 資源優(yōu)化問(wèn)題:某些場(chǎng)景為了避免 TCP 的三次握手和四次揮手的過(guò)程,會(huì)采用 RUDP 來(lái)優(yōu)化資源的占用率和響應(yīng)時(shí)間,提高系統(tǒng)的并發(fā)能力,例如 QUIC。

六、UDP 真的比 TCP 要高效嗎

相信很多同學(xué)都認(rèn)為 UDP 無(wú)連接,無(wú)需重傳和處理確認(rèn),UDP 比較高效。

然而 UDP 在大多情況下并不一定比 TCP 高效,TCP 發(fā)展至今天,為了適應(yīng)各種復(fù)雜的網(wǎng)絡(luò)環(huán)境,其算法已經(jīng)非常豐富,協(xié)議本身經(jīng)過(guò)了很多優(yōu)化,如果能夠合理配置 TCP 的各種參數(shù)選項(xiàng),那么在多數(shù)的網(wǎng)絡(luò)環(huán)境下 TCP 是要比 UDP 更高效的。

影響 UDP 高效因素有以下3點(diǎn):

1、 無(wú)法智能利用空閑帶寬導(dǎo)致資源利用率低:

一個(gè)簡(jiǎn)單的事實(shí)是 UDP 并不會(huì)受到 MTU 的影響,MTU 只會(huì)影響下層的 IP 分片,對(duì)此 UDP 一無(wú)所知。

在極端情況下,UDP 每次都是發(fā)小包,包是 MTU 的幾百分之一,這樣就造成 UDP 包的有效數(shù)據(jù)占比較小 (UDP 頭的封裝成本);

或者,UDP 每次都是發(fā)巨大的 UDP 包,包大小是 MTU 的幾百倍,這樣會(huì)造成下層 IP 層的大量分片,大量分片的情況下,其中某個(gè)分片丟失了,就會(huì)導(dǎo)致整個(gè) UDP 包的無(wú)效。

由于網(wǎng)絡(luò)情況是動(dòng)態(tài)變化的,UDP 無(wú)法根據(jù)變化進(jìn)行調(diào)整,發(fā)包過(guò)大或過(guò)小,從而導(dǎo)致帶寬利用率低下,有效吞吐量較低。

而 TCP 有一套智能算法,當(dāng)發(fā)現(xiàn)數(shù)據(jù)必須積攢的時(shí)候,就說(shuō)明此時(shí)不積攢也不行,TCP 的復(fù)雜算法會(huì)在延遲和吞吐量之間達(dá)到一個(gè)很好的平衡。

2、無(wú)法動(dòng)態(tài)調(diào)整發(fā)包:

由于 UDP 沒(méi)有確認(rèn)機(jī)制,沒(méi)有流量控制和擁塞控制,這樣在網(wǎng)絡(luò)出現(xiàn)擁塞 或 通信兩端處理能力不匹配的時(shí)候,UDP 并不會(huì)進(jìn)行調(diào)整發(fā)送速率,從而導(dǎo)致大量丟包。

在丟包的時(shí)候,不合理的簡(jiǎn)單重傳策略會(huì)導(dǎo)致重傳風(fēng)暴,進(jìn)一步加劇網(wǎng)絡(luò)的擁塞,從而導(dǎo)致丟包率雪上加霜。

更加嚴(yán)重的是,UDP 的 無(wú)秩序性和自私性,一個(gè)瘋狂的 UDP 程序可能會(huì)導(dǎo)致這個(gè)網(wǎng)絡(luò)的擁塞,擠壓其他程序的流量帶寬,導(dǎo)致所有業(yè)務(wù)質(zhì)量都下降。

3、改進(jìn) UDP 的成本較高:

可能有同學(xué)想到針對(duì) UDP 的一些缺點(diǎn),在用戶態(tài)做些調(diào)整改進(jìn),添加上簡(jiǎn)單的重傳和動(dòng)態(tài)發(fā)包大小優(yōu)化。

然而,這樣的改進(jìn)并比簡(jiǎn)單的,UDP 編程可是比 TCP 要難不少的,考慮到改造成本,為什么不直接用TCP呢?

當(dāng)然可以拿開(kāi)源的一些實(shí)現(xiàn)來(lái)抄一下(例如:libjingle),或者擁抱一下 Google 的 QUIC 協(xié)議,然而,這些都需要不少成本的。

上面說(shuō)了這么多,難道真的不該用UDP了嗎?

其實(shí)也不是的,在某些場(chǎng)景下,我們還是必須 UDP 才行的。那么 UDP 的較為合適的使用場(chǎng)景是哪些呢?

七、UDP 協(xié)議的正確使用場(chǎng)合

1、高通信 實(shí)時(shí)性要求 和 低持續(xù)性要求 的場(chǎng)景下

在分組交換通信當(dāng)中,協(xié)議棧的成本主要表現(xiàn)在以下兩方面:

[1] 封裝帶來(lái)的空間復(fù)雜度;

[2] 緩存帶來(lái)的時(shí)間復(fù)雜度。

以上兩者是對(duì)立影響的,如果想減少封裝消耗,那么就必須緩存用戶數(shù)據(jù)到一定量在一次性封裝發(fā)送出去,這樣每個(gè)協(xié)議包的有效載荷將達(dá)到最大化,這無(wú)疑是節(jié)省了帶寬空間,帶寬利用率較高,但是延時(shí)增大了。

如果想降低延時(shí),那么就需要將用戶數(shù)據(jù)立馬封裝發(fā)出去,這樣顯然會(huì)造成消耗更多的協(xié)議頭等消耗,浪費(fèi)帶寬空間。

因此,我們進(jìn)行協(xié)議選擇的時(shí)候,需要重點(diǎn)考慮一下空間復(fù)雜度 和 時(shí)間復(fù)雜度間 的 平衡。

通信的持續(xù)性對(duì)兩者的影響比較大,根據(jù)通信的持續(xù)性有兩種通信類型:

[1] 短連接通信;

[2] 長(zhǎng)連接通信。

對(duì)于短連接通信:

一方面如果業(yè)務(wù)只需要發(fā)一兩個(gè)包并且對(duì)丟包有一定的容忍度,同時(shí)業(yè)務(wù)自己有簡(jiǎn)單的輪詢或重復(fù)機(jī)制,那么采用 UDP 會(huì)較為好些。

在這樣的場(chǎng)景下,如果用 TCP,僅僅握手就需要 3 個(gè)包,這樣顯然有點(diǎn)不劃算,一個(gè)典型的例子是 DNS 查詢。

另一方面,如果業(yè)務(wù)實(shí)時(shí)性要求非常高,并且不能忍受重傳,那么首先就是 UDP 了或者只能用 UDP 了,例如 NTP 協(xié)議,重傳 NTP 消息純屬添亂(為什么呢?重傳一個(gè)過(guò)期的時(shí)間包過(guò)來(lái),還不如發(fā)一個(gè)新的 UDP 包同步新的時(shí)間過(guò)來(lái))。

如果 NTP 協(xié)議采用 TCP,撇開(kāi)握手消耗較多數(shù)據(jù)包交互的問(wèn)題,由于 TCP 受 Nagel 算法等影響,用戶數(shù)據(jù)會(huì)在一定情況下會(huì)被內(nèi)核緩存延后發(fā)送出去,這樣時(shí)間同步就會(huì)出現(xiàn)比較大的偏差,協(xié)議將不可用。

2、多點(diǎn)通信的場(chǎng)景下

對(duì)于一些多點(diǎn)通信的場(chǎng)景,如果采用有連接的 TCP,那么就需要和多個(gè)通信節(jié)點(diǎn)建立其雙向連接,然后有時(shí)在 NAT 環(huán)境下,兩個(gè)通信節(jié)點(diǎn)建立其直接的 TCP 連接不是一個(gè)容易的事情,在涉及 NAT 穿越的時(shí)候,UDP 協(xié)議的無(wú)連接性使得穿透成功率更高.

(原因詳見(jiàn):由于 UDP 的無(wú)連接性,那么其完全可以向一個(gè)組播地址發(fā)送數(shù)據(jù)或者輪轉(zhuǎn)地向多個(gè)目的地持續(xù)發(fā)送相同的數(shù)據(jù),從而更為容易實(shí)現(xiàn)多點(diǎn)通信。)

一個(gè)典型的場(chǎng)景是:

多人實(shí)時(shí)音視頻通信,這種場(chǎng)景下實(shí)時(shí)性要求比較高,可以容忍一定的丟包率。

比如:對(duì)于音頻,對(duì)端連續(xù)發(fā)送 p1、p2、p3 三個(gè)包,另一端收到了 p1 和 p3,在沒(méi)收到 p2 的保持 p1 的最后一個(gè)音(也是為什么有時(shí)候網(wǎng)絡(luò)丟包就會(huì)聽(tīng)到嗞嗞嗞嗞嗞嗞…或者卟卟卟卟卟卟卟卟…重音的原因),等到到 p3 就接著播 p3 了,不需要也不能補(bǔ)幀,一補(bǔ)就越來(lái)越大的延時(shí)。

對(duì)于這樣的場(chǎng)景就比較合適用 UDP 了,如果采用 TCP,那么在出現(xiàn)丟包的時(shí)候,就可能會(huì)出現(xiàn)比較大的延時(shí)。

3、UDP應(yīng)用舉例

通常情況下,UDP 的使用范圍是較小的,在以下的場(chǎng)景下,使用 UDP 才是明智的。

[1]實(shí)時(shí)性要求很高,并且?guī)缀醪荒苋萑讨貍鳎?例子:NTP 協(xié)議,實(shí)時(shí)音視頻通信,直播、實(shí)時(shí)游戲、多人動(dòng)作類游戲中人物動(dòng)作、位置。
[2] TCP 實(shí)在不方便實(shí)現(xiàn)多點(diǎn)傳輸?shù)那闆r;
[3]需要進(jìn)行 NAT 穿越;
[4]對(duì)網(wǎng)絡(luò)狀態(tài)很熟悉,確保 udp 網(wǎng)絡(luò)中沒(méi)有氓流行為,瘋狂搶帶寬;
[5]熟悉 UDP 編程。

UDP本身是不可靠,現(xiàn)在需要保證可靠,在不改變 UDP 協(xié)議的情況下能夠想到的是在應(yīng)用層做可靠性設(shè)計(jì),但是應(yīng)用層做可能通用性會(huì)差一些,那么在傳輸層和應(yīng)用層之間加一層實(shí)現(xiàn)UDP的可靠性呢?

基于這個(gè)想法提出了RUDP(Reliable UDP),實(shí)際上,已經(jīng)有項(xiàng)目在這么做了,比如 Google 的 QUIC 和 WebRTC。

據(jù)了解,目前國(guó)內(nèi)廠商做實(shí)時(shí)傳輸一般都會(huì)考慮 RUDP。

4、QQ udp 淺析

1>、用 tcp 長(zhǎng)連接,對(duì)服務(wù)器的負(fù)擔(dān)很大

首先每一個(gè) QQ 客戶端實(shí)際上都適合服務(wù)器交互,再由服務(wù)器轉(zhuǎn)發(fā)給正在通信的用戶,如果每一個(gè) QQ 從一上線到下線的這段時(shí)間全部采用 tcp 長(zhǎng)連接,這對(duì)服務(wù)器的負(fù)擔(dān)很大,而如果采用 tcp 短連接,頻繁的連接斷開(kāi)也會(huì)造成網(wǎng)絡(luò)負(fù)擔(dān),而采用 udp 則可以避開(kāi)上述麻煩,減少服務(wù)器的負(fù)擔(dān)。

不管 udp 還是 tcp,最終登陸成功之后,QQ 都會(huì)有一個(gè) tcp 連接來(lái)保持在線狀態(tài)。這個(gè) tcp 連接的遠(yuǎn)程端口一般是80,采用 udp 方式登陸的時(shí)候,端口是8000。

udp 協(xié)議是無(wú)連接方式的協(xié)議,它的效率高,速度快,占資源少,但是其傳輸機(jī)制為不可靠傳送,必須依靠輔助的算法來(lái)完成傳輸控制。

QQ 采用的通信協(xié)議以 udp 為主,輔以 tcp 協(xié)議。由于 QQ 的服務(wù)器設(shè)計(jì)容量是海量級(jí)的應(yīng)用,一臺(tái)服務(wù)器要同時(shí)容納十幾萬(wàn)的并發(fā)連接,因此服務(wù)器端只有采用 udp 協(xié)議與客戶端進(jìn)行通訊才能保證這種超大規(guī)模的服務(wù)。

2>、tcp 較難實(shí)現(xiàn) NAT 穿越

QQ 客戶端之間的消息傳送也采用了 udp 模式,因?yàn)閲?guó)內(nèi)的網(wǎng)絡(luò)環(huán)境非常復(fù)雜,而且很多用戶采用的方式是通過(guò)代理服務(wù)器共享一條線路上網(wǎng)的方式

在這些復(fù)雜的情況下,客戶端之間能彼此建立起來(lái) tcp 連接的概率較小,嚴(yán)重影響傳送信息的效率。

而 udp 包能夠穿透大部分的代理服務(wù)器,因此 QQ 選擇了 udp 作為客戶之間的主要通信協(xié)議。采用 udp 協(xié)議,通過(guò)服務(wù)器中轉(zhuǎn)方式。因此,現(xiàn)在的 IP 偵探在你僅僅跟對(duì)方發(fā)送聊天消息的時(shí)候是無(wú)法獲取到IP的。

3>、讓 UDP 變得可靠

大家都知道,udp 協(xié)議是不可靠協(xié)議,它只管發(fā)送,不管對(duì)方是否收到的,但它的傳輸很高效。

但是作為聊天軟件,怎么可以采用這樣的不可靠方式來(lái)傳輸消息呢?

于是,騰訊采用了上層協(xié)議來(lái)保證可靠傳輸:如果客戶端使用 udp 協(xié)議發(fā)出消息后,服務(wù)器收到該包,需要使用 udp 協(xié)議發(fā)回一個(gè)應(yīng)答包,如此來(lái)保證消息可以無(wú)遺漏傳輸。

之所以會(huì)發(fā)生在客戶端明明看到"消息發(fā)送失敗"但對(duì)方又收到了這個(gè)消息的情況,就是因?yàn)榭蛻舳税l(fā)出的消息服務(wù)器已經(jīng)收到并轉(zhuǎn)發(fā)成功,但客戶端由于網(wǎng)絡(luò)原因沒(méi)有收到服務(wù)器的應(yīng)答包引起的。

QQ 并不是端對(duì)端的聊天軟件,是得經(jīng)過(guò)服務(wù)器轉(zhuǎn)發(fā)消息的,通過(guò) QQ 聊天,數(shù)據(jù)是 A 發(fā)到服務(wù)器,服務(wù)器再轉(zhuǎn)發(fā)到 B。

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • UDP
    UDP
    +關(guān)注

    關(guān)注

    0

    文章

    317

    瀏覽量

    33801
  • 數(shù)據(jù)包
    +關(guān)注

    關(guān)注

    0

    文章

    238

    瀏覽量

    24244

原文標(biāo)題:UDP 分片 與 丟包,UDP 真的比 TCP 高效嗎?UDP 的應(yīng)用場(chǎng)景

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    深度解析TCPUDP協(xié)議

    計(jì)算機(jī)與網(wǎng)絡(luò)設(shè)備要相互通信,它們必須遵循一種共同的方法或標(biāo)準(zhǔn)。對(duì)于不同硬件平臺(tái)和操作系統(tǒng)之間的交互而言,這種共同遵循的規(guī)范尤為關(guān)鍵。我們將這一系列指導(dǎo)通信過(guò)程的規(guī)則稱為“協(xié)議”。TCPUDP
    的頭像 發(fā)表于 09-02 14:53 ?176次閱讀
    深度解析<b class='flag-5'>TCP</b>與<b class='flag-5'>UDP</b>協(xié)議

    tcpudp的區(qū)別和聯(lián)系

    一、引言 在現(xiàn)代網(wǎng)絡(luò)通信中,數(shù)據(jù)傳輸是至關(guān)重要的。為了確保數(shù)據(jù)的可靠傳輸,網(wǎng)絡(luò)協(xié)議發(fā)揮著關(guān)鍵作用。傳輸控制協(xié)議(TCP)和用戶數(shù)據(jù)報(bào)協(xié)議(UDP)是兩種常用的網(wǎng)絡(luò)協(xié)議,它們?cè)谠S多應(yīng)用場(chǎng)景中發(fā)
    的頭像 發(fā)表于 08-16 11:06 ?321次閱讀

    udp數(shù)據(jù)的原因?

    編譯sdk/examples/protocols/sockets/udp_server 例子程序,修改了代碼,把發(fā)送回去的代碼注釋,只是記錄上次接收數(shù)據(jù)的時(shí)間和當(dāng)前接收數(shù)據(jù)的時(shí)間間隔,運(yùn)行一個(gè)
    發(fā)表于 06-25 07:03

    esp32 udp broadcast怎么避免?

    esp32 udp broadcast
    發(fā)表于 06-17 06:05

    STM32F4使用lwip無(wú)法發(fā)送udp怎么解決?

    STM32F407ZG 2. lwip是用stm32cubemx自動(dòng)生成的 3. 這個(gè)項(xiàng)目可以接收tcp,可以發(fā)送tcp,可以收到udp,就是不能發(fā)送。 4. 核心函數(shù)如下: w
    發(fā)表于 04-26 06:54

    udp是什么協(xié)議?udp協(xié)議介紹

    要求不高,但對(duì)時(shí)延和帶寬有要求的應(yīng)用場(chǎng)景。 UDP協(xié)議的主要特點(diǎn)包括: 1. 無(wú)連接:UDP不需要建立連接,可以直接發(fā)送數(shù)據(jù)。 2. 輕量級(jí):UDP沒(méi)有TCP那么復(fù)雜的控制機(jī)制,頭部信
    的頭像 發(fā)表于 04-19 15:57 ?930次閱讀

    通信必備知識(shí)!TCPUDP協(xié)議介紹及使用

    TCPUDP是兩個(gè)最常用的通訊協(xié)議。TCP是面向連接的協(xié)議,需要在收發(fā)數(shù)據(jù)前與對(duì)方建立可靠的連接,建立連接的過(guò)程為3次握手,斷開(kāi)連接的過(guò)程為4次揮手,確保數(shù)據(jù)傳輸?shù)目煽啃浴?b class='flag-5'>UDP是一
    的頭像 發(fā)表于 03-15 08:19 ?1543次閱讀
    通信必備知識(shí)!<b class='flag-5'>TCP</b>與<b class='flag-5'>UDP</b>協(xié)議介紹及使用

    udp是什么意思 簡(jiǎn)述TCPUDP的區(qū)別和聯(lián)系

    UDP (User Datagram Protocol) 是一種在計(jì)算機(jī)網(wǎng)絡(luò)中使用的傳輸層協(xié)議。它與TCP (Transmission Control Protocol) 一樣,都是在因特網(wǎng)協(xié)議套件
    的頭像 發(fā)表于 02-02 16:33 ?1003次閱讀

    UDPTCP的主要區(qū)別 UDP能否像TCP一樣實(shí)現(xiàn)可靠傳輸?

    的傳輸不進(jìn)行確認(rèn)和重傳,而TCP是一種面向連接的協(xié)議,通過(guò)確認(rèn)和重傳來(lái)實(shí)現(xiàn)可靠的數(shù)據(jù)傳輸。 首先,UDP無(wú)連接的特點(diǎn)使得它在傳輸時(shí)的開(kāi)銷較小。UDP的數(shù)據(jù)不需要建立和維護(hù)連接,僅包括
    的頭像 發(fā)表于 01-22 16:10 ?605次閱讀

    UDP分片TCP效果對(duì)比

    UDP(用戶數(shù)據(jù)報(bào)協(xié)議)和TCP(傳輸控制協(xié)議)在很多方面都有顯著的區(qū)別??傮w來(lái)說(shuō),TCP更適合需要可靠傳輸?shù)膽?yīng)用,例如網(wǎng)頁(yè)瀏覽、電子郵件等,而UDP則更適合對(duì)速度有高要求,但對(duì)數(shù)據(jù)完
    的頭像 發(fā)表于 11-23 13:55 ?501次閱讀

    UDP的特性與應(yīng)用場(chǎng)景

    基于UDP的低時(shí)延的互聯(lián)網(wǎng)傳輸層協(xié)議 詳情可參閱: https://eng.uber.com/employing-quic-protocol/ UDP傳輸時(shí)需要注意的問(wèn)題 數(shù)據(jù)確認(rèn)機(jī)制 數(shù)據(jù)
    的頭像 發(fā)表于 11-13 15:34 ?740次閱讀
    <b class='flag-5'>UDP</b>的特性與應(yīng)用場(chǎng)景

    TCPUDP的基本區(qū)別

    TCPUDP基本區(qū)別 基于連接與無(wú)連接 TCP要求系統(tǒng)資源較多,UDP較少; UDP程序結(jié)構(gòu)較簡(jiǎn)單 流模式(
    的頭像 發(fā)表于 11-13 15:27 ?4397次閱讀
    <b class='flag-5'>TCP</b>與<b class='flag-5'>UDP</b>的基本區(qū)別

    接收UDP報(bào)文的過(guò)程

    最近工作中遇到某個(gè)服務(wù)器應(yīng)用程序 UDP ,在排查過(guò)程中查閱了很多資料,總結(jié)出來(lái)這篇文章,供更多人參考。 在開(kāi)始之前,我們先用一張圖解釋 linux 系統(tǒng)接收網(wǎng)絡(luò)報(bào)文的過(guò)程。 首先網(wǎng)絡(luò)報(bào)文通過(guò)
    的頭像 發(fā)表于 11-11 11:22 ?751次閱讀
    接收<b class='flag-5'>UDP</b>報(bào)文的過(guò)程

    TCPUDP的區(qū)別

    1.TCPUDP的區(qū)別 TCP是面向連接的,UDP是面向無(wú)連接的; TCP只能一對(duì)一通信,UDP
    的頭像 發(fā)表于 11-09 09:35 ?3304次閱讀
    <b class='flag-5'>TCP</b>和<b class='flag-5'>UDP</b>的區(qū)別

    TCP/UDP簡(jiǎn)介、特點(diǎn)及優(yōu)劣勢(shì)

    TCPUDP是兩種常見(jiàn)的互聯(lián)網(wǎng)傳輸協(xié)議,它們都是在IP網(wǎng)絡(luò)上運(yùn)行的傳輸層協(xié)議。
    的頭像 發(fā)表于 10-16 10:16 ?2475次閱讀
    <b class='flag-5'>TCP</b>/<b class='flag-5'>UDP</b>簡(jiǎn)介、特點(diǎn)及優(yōu)劣勢(shì)