TCP與UDP區別詳解

xiaxveliang發表於2020-05-19

TCP與UDP區別詳解

計算機與其他網路裝置相互通訊,通訊的雙方在傳送和接收資料包時必須基於相同的規則(例如:如何找到通訊目標、如何發起通訊、如何結束通訊等規則都需要事先確定),我們將這種規則稱為協議(Protocol)。

TCP/IP協議簇是 Internet 的基礎,其是一系列網路協議的總稱,例如:TCP、UDP、IP、FTP、HTTP、ICMP、SMTP等都屬於TCP/IP協議族內的協議。
這些協議在計算機網路中自下而上被劃分為四層:鏈路層、網路層、傳輸層和應用層。

  • 鏈路層:
    負責傳送和接收ARP/RARP報文;
  • 網路層:
    該層包含IP協議、RIP協議(Routing Information Protocol),主要負責資料包在主機之間的傳輸
  • 傳輸層:
    主要負責定位處理資料的具體程式並轉發資料(TCP協議提供可靠的資料流運輸服務,UDP協議提供不可靠的資料服務);
  • 應用層
    負責向使用者提供應用程式,比如HTTP、FTP、Telnet、DNS、SMTP等;

開放式系統互聯通訊參考模型

在網路體系結構中網路通訊的建立必須是在通訊雙方的對等層進行,不能交錯。
在整個資料傳輸過程中,資料在傳送端經過各層時都要附加上相應層的協議頭和協議尾(僅鏈路層需要封裝協議尾)。

UDP 與 TCP 兩種傳輸協議是 TCP/IP 協議簇的核心成員。

一、UDP

UDP(User Datagram Protocol)全稱是使用者資料電報協議,是一種無連線的協議,提供不可靠的使用者資料包服務,1980 年釋出的 RFC 768 定義了 UDP 協議。

UDP資料結構

UDP資料結構如下圖所示:
UDP資料

UDP 協議頭中只包含 4 個欄位:源埠、目的埠、UDP長度、UDP校驗碼,其中每一個欄位都佔 16 位,即 2 位元組,共8個位元組。

  • 源埠
    傳送方程式的埠號,接收方可以使用該欄位(不一定準確)向傳送方傳送資訊(範圍0-65535);
  • 目的埠
    資料接收方的埠號(範圍0-65535);
  • UDP長度
    協議頭和資料包中資料長度的總和,表示整個資料包的大小;
  • UDP校驗碼
    使用 IP 首部、UDP 首部和資料包中的資料進行計算,接收方可以通過校驗碼驗證資料的準確性,發現傳輸過程中出現的問題;

UDP首部資料舉例

常見的 DNS 協議就可以使用 UDP 協議獲取域名解析的結果:

0000   ff 7c 00 35 00 23 c2 6e

上述 UDP 首部中四個欄位對應的值如下:

  • 源埠 0xff7c = 65404
  • 目的埠 0x0035 = 53
    由於 DNS 協議使用的埠是 53,所以目的埠就是 53
  • UDP長度 0x0023 = 35
  • UDP校驗碼 0xc26e

UDP在資料傳輸中的位置

這裡我們可以將應用到應用之間的傳輸過程分成兩個部分:
主機到主機的資料傳輸主機到應用的資料轉發

  • UDP 協議首部的目的埠號用於定位處理資料的具體程式並轉發資料;
  • UDP 協議底層的網路層IP協議(Internet Protocol)會負責資料包在主機之間的傳輸;

我們說 UDP 協議是傳輸層協議,但是真正在主機間完成資料傳輸工作的是 IP 協議UDP 協議只起到了定位具體程式的作用。

UDP資料傳輸的特點

  • 面向無連線
    UDP 不需要與 TCP一樣在傳送資料前進行三次握手建立連線,UDP想發資料就直接傳送了;並且UDP只是資料包文的搬運工,不會對資料包文進行任何拆分和拼接操作。
  • 不可靠
    首先不可靠性體現在無連線上,通訊都不需要建立連線,想發就發,這樣的情況肯定不可靠的;並且收到什麼資料就傳遞什麼資料,也不會備份資料,傳送資料也不會關心對方是否已經正確接收到資料;
    再者網路環境時好時壞,但是 UDP 因為沒有擁塞控制,一直會以恆定的速度傳送資料;即使網路條件不好,也不會對傳送速率進行調整,這樣實現的弊端就是在網路條件不好的情況下可能會導致丟包,但是優點也很明顯,在某些實時性要求高的場景(比如直播、電話會議等)就需要使用 UDP 而不是 TCP;
  • 單播、多播、廣播功能
    由於 UDP 不會建立連線,因此它可以給任何人傳遞資料,不止支援一對一的傳輸方式,同樣支援一對多、多對多、多對一的方式;
  • UDP是面向報文的
    傳送方的UDP對應用程式交下來的報文,在新增首部後就向下交付IP層(UDP對應用層交下來的報文,既不合並,也不拆分,而是保留這些報文的邊界);
  • 頭部開銷小,傳輸資料高效
    UDP 的頭部開銷小,只有八位元組,在傳輸資料包文時是比較高效的(在某些實時性要求高的場景,例如直播、電話會議、媒體傳輸等場景經常使用 UDP協議);

UDP資料傳輸

二、TCP

TCP(Transmission Control Protocol)協議全稱是傳輸控制協議,是一種面向連線的、可靠的、基於位元組流的傳輸層通訊協議,由RFC 793定義。

當使用者檢視網頁或電子郵件時,希望看到的內容完整且順序正確,不丟失任何內容;當下載檔案時,希望獲得的是完整的檔案,而不僅僅是檔案的一部分;以上應用場景的傳輸層協議均可採用TCP協議。

TCP資料結構

TCP資料結構

  • 源埠、目標埠
    傳送方程式的埠號,資料接收方的埠號(範圍0-65535);
  • 序號
    主要是為了解決亂序問題(編好號才知道哪個先來,哪個後到);
  • 確認序號
    發出去的包應該有確認,這樣能知道對方是否收到,如果沒收到就應該重新傳送,這個解決的是不丟包的問題;
  • 狀態位
    SYN 是發起一個連結,ACK 是回覆,RST 是重新連線,FIN 是結束連線(TCP 是面向連線的,因此需要雙方維護連線的狀態,這些狀態位的包會引起雙方的狀態變更);
  • 視窗大小
    TCP 要做流量控制,需要通訊雙方各宣告一個視窗,標識自己當前的處理能力;

TCP三次握手

TCP協議傳送資料之前必須在通訊的兩端建立連線,建立連線的方法是TCP三次握手

TCP三次握手

  • 第一次握手
    客戶端向服務端傳送連線請求報文;請求傳送後,客戶端便進入 SYN-SENT 狀態;
  • 第二次握手
    服務端收到連線請求報文後,如果同意連線,則會傳送一個應答,傳送完成後便進入 SYN-RECEIVED 狀態;
  • 第三次握手
    當客戶端收到連線同意的應答後,還要向服務端傳送一個確認報文;客戶端發完這個報文後便進入 ESTABLISHED 狀態,服務端收到這個應答後也進入 ESTABLISHED 狀態,此時連線建立成功。

為什麼 TCP 建立連線需要三次握手,而不是兩次?
TCP既要保證資料可靠傳輸,又要提高傳輸的效率,而用三次(客戶端與服務端傳送的報文都得到了響應,通訊雙方全都有來有回)恰恰滿足了以上兩方面的需求!

TCP三次握手

TCP四次揮手

TCP斷開連線,也被稱為四次揮手:

enter description here

  • 第一次揮手
    A:B,我不玩了
    客戶端A服務端B傳送連線釋放請求;
  • 第二次揮手
    B:OK,A不玩了,知道了
    服務端B 收到連線釋放請求後,傳送 ACK 包,並進入 CLOSE_WAIT 狀態;
    此時服務端B不再接收客戶端A傳送的資料,但服務端B 若此時還有沒發完的資料會繼續傳送;
  • 第三次揮手
    B:A,我也不玩了,拜拜
    服務端 B 向 A 傳送連線釋放請求,然後 B 便進入 LAST-ACK 狀態;
  • 第四次揮手
    A:OK,B不玩了,拜拜
    客戶端A 收到釋放請求後,向 服務端B 傳送確認應答,此時 客戶端A 進入 TIME-WAIT 狀態;
    客戶端A的 TIME-WAIT狀態會持續 2MSL(最大段生存期,指報文段在網路中生存的時間,超時會被拋棄) 時間,若該時間段內沒有 B 的重發請求,就進入 CLOSED 狀態。當 B 收到確認應答後,也便進入 CLOSED 狀態。

TCP協議的特點

相比與UDP協議,TCP協議擁有面向連線、保證順序、可靠傳輸、提供擁塞控制等特點。

為了保證順序性,每個TCP資料包都有一個序號ID,在建立連線的時候會商定起始 ID 是什麼,然後按照 ID 一個個傳送;
為了保證不丟包,需要對傳送的包都要進行應答,這裡應答不是一個一個來的,而是會應答某個之前的 ID,表示都收到了,這種模式成為累計應答
為了記錄所有傳送的包和接收的包,需要傳送端接收端分別快取這些記錄。

TCP傳送端的快取裡是按照資料包的 序號ID 一個個排列,根據處理的情況分成四個部分:

  • 傳送並且確認的;
  • 傳送尚未確認的;
  • 沒有傳送等待傳送的;
  • 沒有傳送並且暫時不會傳送的;

TCP傳送端快取結構

在 TCP 協議中接收端會給傳送端報一個視窗大小Advertised Window,這個視窗大小等於上面的第二、第三部分加和,超過這個視窗接收端處理不過來,暫時不能繼續傳送;

上圖TCP傳送端快取佇列中:

  • 1、2、3 已傳送並確認;
  • 4、5、6、7、8、9 都是傳送了還沒確認;
  • 10、11、12 是還沒發出的;
  • 13、14、15 是接收方沒有空間,不準備發的。

TCP接收端快取內容型別如下:

  • 接收並且確認過的;
  • 還沒接收,馬上就能接收的;
  • 還沒接收,也無法接收的;

TCP接收端快取結構

上圖TCP接收端快取佇列中:

  • 1、2、3、4、5 是已經完成 ACK ;
  • 6、7 是等待接收的,8、9 是已經接收還沒有 ACK 的;
  • 10、11、12 、13、14、15 是暫時無法接收的;

TCP傳送端、接收端當前的狀態如下(依據以上兩個圖):

  • 1、2、3 沒有問題,雙方達成了一致;
  • 4、5 接收方響應 ACK 了,但是傳送方尚未收到;
  • 6、7、8、9 肯定都發了,而且8、9 已經到了,但6、7 尚未收到,出現了亂序,快取著暫無法 ACK;

根據這個例子可以知道順序問題和丟包問題都有可能存在:

假設4的ACK響應傳送端收到了,5的ACK丟了;6、7的資料包丟了,該怎麼辦?

  • 一種方法是超時重試,即對每一個傳送了但是沒有 ACK 的包設定一個定時器,超過了一定的事件就重新嘗試;這個重試時間必須大於往返時間,但也不宜過長,否則超時時間變長,訪問就變慢了;
    例如:過一段時間,5、6、7 的ACK都超時了,傳送端就會重新傳送;接收方發現 5 原來接收過 於是丟棄 5,6、7收到了傳送 ACK;
  • 另一個快速重傳的機制,即當接收方接收到一個序號大於期望的報文段時,就檢測資料流之間的間隔,於是傳送三個冗餘的 ACK,客戶端接收到之後,知道資料包丟失,於是重傳丟失的報文段;
    例如:接收方發現 6、8、9 都接收了,但是 7 沒來(7丟了),於是傳送三個 6 的 ACK,要求下一個是 7;客戶端接收到 3 個ACK,就會發現 7 丟了,馬上重發。

參考

UDP—RFC768:
https://tools.ietf.org/html/rfc768

TCP—RFC973:
https://tools.ietf.org/html/rfc793

Stackoverflow: UDP checksum calculation, Sep 2017
https://stackoverflow.com/questions/1480580/udp-checksum-calculation

百度百科—UDP:
https://baike.baidu.com/item/UDP/571511?fr=aladdin

百度百科—TCP:
https://baike.baidu.com/item/TCP/33012?fr=aladdin

TCP 和 UDP 的區別:
https://blog.csdn.net/zhang6223284/article/details/81414149#comments

一文搞懂TCP與UDP的區別
https://www.cnblogs.com/fundebug/p/differences-of-tcp-and-udp.html

========== THE END ==========

wx_gzh.jpg

相關文章