最頭疼的問題莫過於到底該選TCP仍是UDP做爲傳輸層協議。經過快速對比分析 TCP 和 UDP 的區別,來幫助即時通信初學者快速瞭解這些基礎的知識點,從而在IM、消息推送等網絡通訊應用場景中能準確地選擇合適的傳輸層協議。算法
說到 TCP 創建鏈接,相信大多數人腦海裏確定能夠浮現出一個詞,沒錯就是--「三次握手」。TCP 經過「三次握手」來創建鏈接,再經過「四次揮手」斷開一個鏈接。在每次揮手中 TCP 作了哪些操做呢?緩存
流程以下圖所示(TCP的三次握手和四次揮手):網絡
上圖就從客戶端和服務端的角度,清楚的展現了 TCP 的三次握手和四次揮手。能夠看到,當 TCP 試圖創建鏈接時,三次握手指的是客戶端主動觸發了兩次,服務端觸發了一次。socket
咱們能夠先明確一下 TCP 創建鏈接而且初始化的目標是什麼呢?性能
因此三次握手的次序是這樣子的:優化
其中的 2 、3 步驟能夠簡化爲一步,也就是說將 ACK 確認包和 SYN 序列化包一同發送給 Client 端。到此咱們就比較簡單的解釋了 TCP 創建鏈接的「三次握手」。spa
咱們都知道 TCP 是面向鏈接的、可靠的、有序的傳輸層協議,而 UDP 是面向數據報的、不可靠的、無序的傳輸協議,因此 UDP 壓根不會創建什麼鏈接。視頻
就比如發短信同樣,UDP 只須要知道對方的 ip 地址,將數據報一份一份的發送過去就能夠了,其餘的做爲發送方,都不須要關心。server
關於 TCP、UDP 之間數據發送的差別,能夠體現兩者最大的不一樣之處:ip
那麼每次 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
對於 TCP 來講,自己 TCP 有着超時重傳、錯誤重傳、還有等等一系列複雜的算法保證了 TCP 的數據是有序的,假設你發送了數據 一、二、3,則只要發送端和接收端保持鏈接時,接收端收到的數據始終都是 一、二、3。
而 UDP 協議則要奔放的多,不管 server 端不管緩衝池的大小有多大,接收 client 端發來的消息老是一個一個的接收。
而且因爲 UDP 自己的不可靠性以及無序性,若是 client 發送了 一、二、3 這三個數據報過來,server 端接收到的多是任意順序、任意個數三個數據報的排列組合。
其實你們都知道 TCP 自己是可靠的協議,而 UDP 是不可靠的協議。
TCP 內部的不少算法機制讓他保持鏈接的過程當中是很可靠的。好比:TCP 的超時重傳、錯誤重傳、TCP 的流量控制、阻塞控制、慢熱啓動算法、擁塞避免算法、快速恢復算法 等等。
因此 TCP 是一個內部原理複雜,可是使用起來比較簡單的這麼一個協議。
UDP 是一個面向非鏈接的協議,UDP 發送的每一個數據報帶有本身的 IP 地址和接收方的 IP 地址,它自己對這個數據報是否出錯,是否到達不關心,只要發出去了就行了。
因此來研究下,什麼狀況會致使 UDP 丟包:
在文章最後的一部分,聊聊 TCP、UDP 使用場景。
先來講 UDP 的吧,有不少人都會以爲 UDP 與 TCP 相比,在性能速度上是佔優點的。
由於 UDP 並不用保持一個持續的鏈接,也不須要對收發包進行確認。
但事實上通過這麼多年的發展 TCP 已經擁有足夠多的算法和優化,在網絡狀態不錯的狀況下,TCP 的總體性能是優於 UDP 的。
那在何時咱們非用 UDP 不可呢?
以上咱們說了 UDP 的使用場景,在此以外的其餘狀況,使用 TCP 準沒錯。
畢竟有一句話嘛:
when in doubt,use TCP。