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 協定頭中隻包含 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協定);
二、TCP
TCP(Transmission Control Protocol)協定全稱是傳輸控制協定,是一種面向連接配接的、可靠的、基于位元組流的傳輸層通信協定,由RFC 793定義。
當使用者檢視網頁或電子郵件時,希望看到的内容完整且順序正确,不丢失任何内容;當下載下傳檔案時,希望獲得的是完整的檔案,而不僅僅是檔案的一部分;以上應用場景的傳輸層協定均可采用TCP協定。
TCP資料結構
-
源端口、目标端口
發送方程序的端口号,資料接收方的端口号(範圍0-65535);
-
序号
主要是為了解決亂序問題(編好号才知道哪個先來,哪個後到);
-
确認序号
發出去的包應該有确認,這樣能知道對方是否收到,如果沒收到就應該重新發送,這個解決的是不丢包的問題;
-
狀态位
SYN 是發起一個連結,ACK 是回複,RST 是重新連接配接,FIN 是結束連接配接(TCP 是面向連接配接的,是以需要雙方維護連接配接的狀态,這些狀态位的包會引起雙方的狀态變更);
-
視窗大小
TCP 要做流量控制,需要通信雙方各聲明一個視窗,辨別自己目前的處理能力;
TCP三向交握
TCP協定發送資料之前必須在通信的兩端建立連接配接,建立連接配接的方法是
TCP三向交握
:
-
第一次握手
用戶端向服務端發送連接配接請求封包;請求發送後,用戶端便進入 SYN-SENT 狀态;
-
第二次握手
服務端收到連接配接請求封包後,如果同意連接配接,則會發送一個應答,發送完成後便進入 SYN-RECEIVED 狀态;
-
第三次握手
當用戶端收到連接配接同意的應答後,還要向服務端發送一個确認封包;用戶端發完這個封包後便進入 ESTABLISHED 狀态,服務端收到這個應答後也進入 ESTABLISHED 狀态,此時連接配接建立成功。
為什麼 TCP 建立連接配接需要三次握手,而不是兩次?
TCP既要保證資料可靠傳輸,又要提高傳輸的效率,而用三次(
用戶端與服務端發送的封包都得到了響應,通信雙方全都有來有回
)恰恰滿足了以上兩方面的需求!
TCP四次揮手
TCP斷開連接配接,也被稱為四次揮手:
- 第一次揮手
A:B,我不玩了
向用戶端A
發送連接配接釋放請求;服務端B
- 第二次揮手
B:OK,A不玩了,知道了
服務端B 收到連接配接釋放請求後,發送 ACK 包,并進入 CLOSE_WAIT 狀态;
此時服務端B不再接收用戶端A發送的資料,但服務端B 若此時還有沒發完的資料會繼續發送;
- 第三次揮手
服務端 B 向 A 發送連接配接釋放請求,然後 B 便進入 LAST-ACK 狀态;B:A,我也不玩了,拜拜
- 第四次揮手
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 協定中接收端會給發送端報一個
視窗大小Advertised Window
,這個視窗大小等于上面的
第二、第三部分加和
,超過這個視窗接收端處理不過來,暫時不能繼續發送;
上圖TCP發送端緩存隊列中:
- 1、2、3 已發送并确認;
- 4、5、6、7、8、9 都是發送了還沒确認;
- 10、11、12 是還沒發出的;
- 13、14、15 是接收方沒有空間,不準備發的。
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
***: UDP checksum calculation, Sep 2017
https://***.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