默認
打賞 發表評論 12
想開發IM:買成品怕坑?租第3方怕貴?找開源自已擼?盡量別走彎路了... 找站長給點建議
網絡編程懶人入門(四):快速理解TCP和UDP的差異
閱讀(48653) | 評論(12 收藏10 淘帖2 2

原作者:MeloDev,本文由即時通訊網重新修訂發布,感謝原作者的無私分享。


1、前言


對于即時通訊開者新手來說,在開始著手編寫IM或消息推送系統的代碼前,最頭疼的問題莫過于到底該選TCP還是UDP作為傳輸層協議。本文延續《網絡編程懶人入門》系列文章的風格,通過快速對比分析 TCP 和 UDP 的區別,來幫助即時通訊初學者快速了解這些基礎的知識點,從而在IM、消息推送等網絡通信應用場景中能準確地選擇合適的傳輸層協議。

即時通訊網的另一篇文章《簡述傳輸層協議TCP和UDP的區別》也闡述了類似的內容,希望能為您提供更多的參考。

2、系列文章


本文是系列文章中的第4篇,本系列文章的大綱如下:


本站的《腦殘式網絡編程入門》也適合入門學習,本系列大綱如下:


如果您覺得本系列文章過于基礎,您可直接閱讀《不為人知的網絡編程》系列文章,該系列目錄如下:


關于移動端網絡特性及優化手段的總結性文章請見:


3、參考資料


TCP/IP詳解 - 第11章·UDP:用戶數據報協議
TCP/IP詳解 - 第17章·TCP:傳輸控制協議
TCP/IP詳解 - 第18章·TCP連接的建立與終止
TCP/IP詳解 - 第21章·TCP的超時與重傳
通俗易懂-深入理解TCP協議(上):理論基礎
通俗易懂-深入理解TCP協議(下):RTT、滑動窗口、擁塞處理
理論經典:TCP協議的3次握手與4次揮手過程詳解
理論聯系實際:Wireshark抓包分析TCP 3次握手、4次揮手過程
技術往事:改變世界的TCP/IP協議(珍貴多圖、手機慎點)
計算機網絡通訊協議關系圖(中文珍藏版)
高性能網絡編程(一):單臺服務器并發TCP連接數到底可以有多少
高性能網絡編程(二):上一個10年,著名的C10K并發連接問題
高性能網絡編程(三):下一個10年,是時候考慮C10M并發問題了
高性能網絡編程(四):從C10K到C10M高性能網絡應用的理論探索
簡述傳輸層協議TCP和UDP的區別
UDP中一個包的大小最大能多大?
為什么QQ用的是UDP協議而不是TCP協議?
移動端即時通訊協議選擇:UDP還是TCP?

4、建立連接方式的差異


4.1TCP


說到 TCP 建立連接,相信大多數人腦海里肯定可以浮現出一個詞,沒錯就是--“三次握手”。TCP 通過“三次握手”來建立連接,再通過“四次揮手”斷開一個連接。在每次揮手中 TCP 做了哪些操作呢?

流程如下圖所示(TCP的三次握手和四次揮手):
網絡編程懶人入門(四):快速理解TCP和UDP的差異_1915184-43e91a9185faa031.jpg

上圖就從客戶端和服務端的角度,清楚的展示了 TCP 的三次握手和四次揮手。可以看到,當 TCP 試圖建立連接時,三次握手指的是客戶端主動觸發了兩次,服務端觸發了一次。

我們可以先明確一下 TCP 建立連接并且初始化的目標是什么呢?

  • 1)初始化資源;
  • 2)告訴對方我的序列號。

所以三次握手的次序是這樣子的:

  • 1)client端首先發送一個SYN包告訴Server端我的初始序列號是X;
  • 2)Server端收到SYN包后回復給client一個ACK確認包,告訴client說我收到了;
  • 3)接著Server端也需要告訴client端自己的初始序列號,于是Server也發送一個SYN包告訴client我的初始序列號是Y;
  • 4)Client收到后,回復Server一個ACK確認包說我知道了。

其中的 2 、3 步驟可以簡化為一步,也就是說將 ACK 確認包和 SYN 序列化包一同發送給 Client 端。到此我們就比較簡單的解釋了 TCP 建立連接的“三次握手”。

4.2UDP


我們都知道 TCP 是面向連接的、可靠的、有序的傳輸層協議,而 UDP 是面向數據報的、不可靠的、無序的傳輸協議,所以 UDP 壓根不會建立什么連接。

就好比發短信一樣,UDP 只需要知道對方的 ip 地址,將數據報一份一份的發送過去就可以了,其他的作為發送方,都不需要關心。

(關于TCP的3次握手和4次揮手文章,可詳見《理論經典:TCP協議的3次握手與4次揮手過程詳解》、《理論聯系實際:Wireshark抓包分析TCP 3次握手、4次揮手過程》)

5、數據發送方式的差異


關于 TCP、UDP 之間數據發送的差異,可以體現二者最大的不同之處:

  • TCP:
    由于 TCP 是建立在兩端連接之上的協議,所以理論上發送的數據流不存在大小的限制。但是由于緩沖區有大小限制,所以你如果用 TCP 發送一段很大的數據,可能會截斷成好幾段,接收方依次的接收。
  • UDP:
    由于 UDP 本身發送的就是一份一份的數據報,所以自然而然的就有一個上限的大小。

那么每次 UDP 發送的數據報大小由哪些因素共同決定呢?

  • UDP協議本身,UDP協議中有16位的UDP報文長度,那么UDP報文長度不能超過2^16=65536;
  • 以太網(Ethernet)數據幀的長度,數據鏈路層的MTU(最大傳輸單元);
  • socket的UDP發送緩存區大小。

先來看第一個因素,UDP 本身協議的報文長度為 2^16 - 1,UDP 包頭占 8 個字節,IP 協議本身封裝后包頭占 20 個字節,所以最終長度為: 2^16 - 1 - 20 - 8 = 65507 字節。

只看第一個因素有點理想化了,因為 UDP 屬于不可靠協議,我們應該盡量避免在傳輸過程中,數據包被分割。所以這里有一個非常重要的概念 MTU -- 也就是最大傳輸單元。

在 Internet 下 MTU 的值為 576 字節,所以在 internet 下使用 UDP 協議,每個數據報最大的字節數為: 576 - 20 - 8 = 548

(有關UDP協議的最大包長限制,詳見《UDP中一個包的大小最大能多大?》)

6、數據有序性的差異


我們再來談談數據的有序性。

6.1TCP


對于 TCP 來說,本身 TCP 有著超時重傳、錯誤重傳、還有等等一系列復雜的算法保證了 TCP 的數據是有序的,假設你發送了數據 1、2、3,則只要發送端和接收端保持連接時,接收端收到的數據始終都是 1、2、3。

6.2UDP


而 UDP 協議則要奔放的多,無論 server 端無論緩沖池的大小有多大,接收 client 端發來的消息總是一個一個的接收。并且由于 UDP 本身的不可靠性以及無序性,如果 client 發送了 1、2、3 這三個數據報過來,server 端接收到的可能是任意順序、任意個數三個數據報的排列組合。

7、可靠性的差異


其實大家都知道 TCP 本身是可靠的協議,而 UDP 是不可靠的協議。

7.1TCP


TCP 內部的很多算法機制讓他保持連接的過程中是很可靠的。比如:TCP 的超時重傳、錯誤重傳、TCP 的流量控制、阻塞控制、慢熱啟動算法、擁塞避免算法、快速恢復算法 等等。所以 TCP 是一個內部原理復雜,但是使用起來比較簡單的這么一個協議。

7.2UDP


UDP 是一個面向非連接的協議,UDP 發送的每個數據報帶有自己的 IP 地址和接收方的 IP 地址,它本身對這個數據報是否出錯,是否到達不關心,只要發出去了就好了。

所以來研究下,什么情況會導致 UDP 丟包:

  • 數據報分片重組丟失:在文章之前我們就說過,UDP 的每個數據報大小多少最合適,事實上 UDP 協議本身規定的大小是 64kb,但是在數據鏈路層有 MTU 的限制,大小大概在 5kb,所以當你發送一個很大的 UDP 包的時候,這個包會在 IP 層進行分片,然后重組。這個過程就有可能導致分片的包丟失。UDP 本身有 CRC 檢測機制,會拋棄掉丟失的 UDP 包;
  • UDP 緩沖區填滿:當 UDP 的緩沖區已經被填滿的時候,接收方還沒有處理這部分的 UDP 數據報,這個時候再過來的數據報就沒有地方可以存了,自然就都被丟棄了。

8、使用場景總結


在文章最后的一部分,聊聊 TCP、UDP 使用場景。

先來說 UDP 的吧,有很多人都會覺得 UDP 與 TCP 相比,在性能速度上是占優勢的。因為 UDP 并不用保持一個持續的連接,也不需要對收發包進行確認。但事實上經過這么多年的發展 TCP 已經擁有足夠多的算法和優化,在網絡狀態不錯的情況下,TCP 的整體性能是優于 UDP 的。

那在什么時候我們非用 UDP 不可呢?

  • 對實時性要求高:比如實時會議,實時視頻這種情況下,如果使用 TCP,當網絡不好發生重傳時,畫面肯定會有延時,甚至越堆越多。如果使用 UDP 的話,即使偶爾丟了幾個包,但是也不會影響什么,這種情況下使用 UDP 比較好;
  • 多點通信:TCP 需要保持一個長連接,那么在涉及多點通訊的時候,肯定需要和多個通信節點建立其雙向連接,然后有時在NAT環境下,兩個通信節點建立其直接的 TCP 連接不是一個容易的事情,而 UDP 可以無需保持連接,直接發就可以了,所以成本會很低,而且穿透性好。這種情況下使用 UDP 也是沒錯的。

以上我們說了 UDP 的使用場景,在此之外的其他情況,使用 TCP 準沒錯。

畢竟有一句話嘛:

when in doubt,use TCP。


(原文鏈接:點此進入,有改動)

附錄:更多網絡編程資料


Java新一代網絡編程模型AIO原理及Linux系統AIO介紹
NIO框架入門(一):服務端基于Netty4的UDP雙向通信Demo演示
NIO框架入門(二):服務端基于MINA2的UDP雙向通信Demo演示
NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通信實戰
NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通信實戰
P2P技術詳解(一):NAT詳解——詳細原理、P2P簡介
P2P技術詳解(二):P2P中的NAT穿越(打洞)方案詳解
P2P技術詳解(三):P2P技術之STUN、TURN、ICE詳解
通俗易懂:快速理解P2P技術中的NAT穿透原理
>> 更多同類文章 ……

即時通訊網 - 即時通訊開發者社區! 來源: - 即時通訊開發者社區!

上一篇:新手請教如何學習網絡編程?下一篇:[已回復] GCDAsyncUdpSocket發送數據時如何設置響應超時時間呢?

本帖已收錄至以下技術專輯

推薦方案
評論 12
好貼,通俗易懂
簽名: 周末了,可以浪了
通俗易懂,簡介明了
通俗易懂
簽名: 新的一天從學習開始
我算是發現了,我的疑問都需要再看下一篇文章才能解決
引用:司空摘星 發表于 2019-02-14 16:11
我算是發現了,我的疑問都需要再看下一篇文章才能解決

一步一步引導你入坑。。
簽名: 《IM要做手機掃碼登陸?先看看微信的掃碼登錄功能技術原理》http://www.4239727.live/thread-2941-1-1.html
學習了
簽名: 哈哈哈
大佬請教一下 視屏一幀是一個udp數據報 如果分辨率夠大 發的字節超過548 那是不是分片發包 但是又說udp是一份份發的 做分片的話 會不會丟包更嚴重,,,請大佬解惑下
引用:搬磚的約德爾人 發表于 2019-04-28 18:23
大佬請教一下 視屏一幀是一個udp數據報 如果分辨率夠大 發的字節超過548 那是不是分片發包 但是又說udp是一 ...

你看看這篇文章《音視頻聊天開發: 5 UDP發送視頻數據的分包和重組
簽名: 《IM要做手機掃碼登陸?先看看微信的掃碼登錄功能技術原理》http://www.4239727.live/thread-2941-1-1.html
學到了
簽名: 冒個泡
懶人一時爽,一直懶人一直爽
簽名: DotNet NB
感謝 感謝
打賞樓主 ×
使用微信打賞! 使用支付寶打賞!

返回頂部
股票配资平台都找股牛网