在上一篇文章裏講到了網絡的分層,提到了TCP/IP組模型,html
以下:git
可是是否有這樣的疑問,爲何網絡要進行分層呢?github
計算機網絡是一個很是複雜的系統,要想在其中兩臺主機創建鏈接,必需要考慮很是多的場景,假如咱們要在兩臺主機之間傳送一個文件,那麼咱們須要考慮的方法具體有下面幾點:web
這裏只列舉了大概幾種狀況,還有其餘不少場景要處理,我這裏就不一一列出來了;算法
從這裏能夠看出,就只是一個文件的傳遞,都須要考慮這麼多場景,可想而知,計算機網絡是何其的複雜;緩存
那麼既然有這些問題存在,讓咱們試想着如何去解決這種問題;服務器
既然場景這麼多,那麼咱們能不能將這些場景進行歸類,而後進行分層,每一類場景交由某個類別去進行處理呢?網絡
答案是:能夠的;socket
上面這個文件的傳送,咱們能夠歸類爲三層:文件傳輸,通信服務,網絡接入這幾層;tcp
看一下大概的流程圖:
固然上面只是咱們的假想,實際上的模塊劃分遠比這個複雜的多;
好比最開始的OSI模型,足足分了七層;
到這裏你是否有疑問了,這樣進行分層的好處有哪些呢?請看下面;
分層的好處:
TCP(傳輸控制協議)和UDP(用戶數據報協議)是傳輸層的協議,基於網絡層IP協議來實現的;
TCP協議爲兩個主機的通信提供可靠性傳輸,經過將數據切分爲適合傳輸的大小,使用超時重傳,確認到達等一系列操做來保證數據能夠準確的進行傳輸;因爲提供了端到端的可靠性傳輸,應用層的軟件就不須要關心傳輸的相關細節了;
UDP協議提供簡單快速的數據傳送,可是不保證數據的準確性,穩定性,所以使用這個協議的應用層的軟件須要考慮穩定性和準確性的問題;
應用程序在通信的時候,須要先創建起鏈接,而創建鏈接的基礎須要先標誌本身的進程id,也就是PID,若是隻是本地通信的話,PID基本上不會有衝突,可是和網絡上的其餘主機通信時,PID的衝突概率就會大大增長;
那麼要怎麼解決這個問題呢?
咱們知道IP層的協議的IP地址在網絡中是惟一的,不會和其餘主機衝突,那麼咱們能夠利用這個來避免端口號衝突,也就是IP地址+端口號的實現;
而這種標識就是socket通信,最終的格式:Socket=(IP地址:端口號);
socket翻譯過來的意思就是插座,用於應用程序經過網絡進行通信,也被稱爲套接字;
套接字能夠看出是兩個應用程序經過傳輸層傳輸數據時,使用的端點,而套接字是一個抽象的概念,具體實現是由計算機來實現的;
好比當前主機要和另一臺主機進行數據的傳輸,會先將數據寫入到socket中,而後經過傳輸層傳輸到另一臺主機的socket中,而後應用程序再從socket中讀取數據;
socket是"打開—讀/寫—關閉"的實現模式,具體實現以下:
TCP是面向鏈接的協議,也就是在進行通訊以前,必須先創建起鏈接,通訊完以後,必需要釋放鏈接;
每條TCP鏈接只能有兩個端點,不能一對多,或者多對一,只能一一對應,不支持多播(multicast)和廣播(broadcast)的傳輸方式;
TCP提供可靠交付,保證數據不出錯,不重複,不丟失而且有序的傳達給對方;
TCP通訊的雙方均可以同時向對方發送數據和接收對方發送的數據,而且在本地設置有發送緩存和接收緩存,用於應用程序發送數據和取數據,這樣應用程序就不用關心數據的發送和接收了,只須要將數據交給傳輸層便可;
流:指的是流入到進程或者從進程流出的字節序列;
應用程序將要傳輸的數據寫入到TCP的發送緩存中,而後TCP再根據實際傳輸,從發送緩存取出必定的字節序列來進行傳輸,而另外一端接收到數據後,會將數據放入到接收緩存中,應用程序再從接收緩存中讀取字節數據;
這其中,應用程序寫入發送緩存的字節序列並不表明就是TCP要發送的字節序列,TCP會將發送緩存中的字節序列拆分紅適合傳輸的序列來進行傳輸;
這個圖只講了大概的流程,實際上數據還得經過IP層和數據鏈路層的封裝才能進行傳輸;
(1)源端口號和目標端口號:每一個TCP段都包含源端口號和目標端口號,用於確認TCP數據的來源和要發送的端口號,而計算機上的程序是經過監聽端口號來獲取TCP數據包的;
(2)序號:用於標記這個TCP包的順序,由於TCP在傳送過程當中,會先將數據切割爲無數個小的數據包,標記了順序以後,在送達到終端時,從新拼接的時候就不會出錯,用於解決數據包錯亂的問題; 既然每一個傳輸的字節都被計數,確認序號包含發送確認的一端所指望收到的下一個序號。所以,確認序號應當是上次已成功收到數據字節序號加1。只有ACK標誌(下面介紹)爲1時確認序號字段纔有效。
(3)確認序號:用於確認接收終端須要接收的下一個包的序號,經過爲當前包的序號+1,用於保證包傳送的順序;
(4)頭部長段:因爲TCP首部包含一個可變的部分,所以須要一個值來表示當前TCP數據的長度,也就是頭部長段;
(5)保留位:留待之後使用;
(6)標誌位:指數據包的屬性,用於控制TCP的狀態機;
URG
: 表示報文段是否包含緊急數據,當URG=1時才表示有緊急數據;
ACK
: 表示報文段確認序號是否有效,當ACK=1才表示有效,而TCP創建鏈接以後,發送報文的標誌位必須是ACK=1;
PSH
: 用於告知接收方是否須要當即將數據傳遞給上層,當PSH=1生效,不然就緩存起來;
RST
: 當RST=1,表示當前連接出現了不可知的錯誤,須要從新創建鏈接以確保正常的通信;
SYN
: 在創建鏈接時使用,當SYN=1時表示用於請求創建鏈接或者相應創建鏈接,用於TCP握手使用;
FIN
: 用於標記數據是否發送完畢,當FIN=1時生效;
(7)窗口:大小有字節表示,申明接收端所指望接收的字節大小,用於流量控制,不至於傳的數據包過大致使接收端接收不了數據,或者傳的數據包太小,致使浪費網絡資源;
(8)校驗和:用於TCP數據的校驗,是TCP傳輸可靠性的保障之一,由發送端填充,接收端進行校驗;
(9)選項:用於額外的功能實現;
TCP狀態機是指網絡通訊過程當中,狀態變化的狀況;
在TCP通訊的三次握手和四次揮手的過程當中,就是TCP狀態變化的過程,因爲TCP是面向鏈接的,具備可靠性的鏈接,每個要通訊的主機都得和對方創建起鏈接,而這過程會經歷鏈接,傳輸,關閉這幾個步驟,在雙方進行通訊的過程,TCP的狀態變化是不同的;
來看一下《計算機網絡》關於狀態機的流程圖:
至於狀態機的變化,咱們下面的三次握手和四次揮手會講到;
對於人類來講,握手錶示雙方友好交互的意思;而對於計算機來講,握手的意義就大不相同了;
來看一下wiki對於計算機握手的定義:
意思就是:在信息傳輸以前,握手用於確認參數和其餘協議特性達成一致;
而對於tcp的握手來講,是兩臺主機之間互相交換一次tcp數據,用於確認參數和序列;每一次握手,主機都得向對方發送一次tcp數據;
1,客戶端發送信息告訴服務端我要進行鏈接;
這時候發起鏈接的主機會先發送一個TCP數據包,數據包含標誌位SYN=1,序列號 seq=x,而後發起鏈接的主機進入SYN-SENT(同步已發送階段);
第一次握手完成;
2,服務端告訴客戶端我收到請求,而且準備好接收數據了;
收到發起鏈接請求的主機會先解析數據,而後發送一個TCP數據包作爲迴應,數據包包含 ACK=1(表示當前確認號有效),SYN=1(表示請求鏈接有效),確認號ack=x+1(表示指望下一次收到TCP數據的序列號), seq=y(表示爲本身初始化一個序列號),而後接收鏈接的主機會進入SYN-RCVD(同步接收狀態);
第二次握手完成;
3,客戶端發送消息表示我要開始發送數據了,服務端收到後表示鏈接創建成功;
發起請求的主機接收到另外一臺主機發送的確認數據後,會再向要鏈接的主機再發送一個確認數據,數據包包含ACK=1(表示當前確認號有效),確認號ack=y+1(表示指望下一次收到TCP數據的序列號),seq=x+1(本身的初始化序列號+1),此時TCP創建鏈接成功,發起鏈接的主機進入ESTABLISHED狀態(表示創建鏈接成功);
第三次握手完成;
TCP鏈接成功創建;
看一下流程圖:
讓我引用《計算機網絡》一書上的說法:
爲了防止已經失效的鏈接請求報文段忽然又傳到服務端,於是產生錯誤;
對於這句話的解讀:
對於從客戶端發送到服務端的請求鏈接的報文,由於網絡上的延遲,或者阻塞等緣由,致使鏈接已經釋放後再被服務端接收到,此時服務端再給客戶端發送報文表示鏈接創建成功;
這時候發送給服務端的報文有多是已經失效的報文了,而服務器在接收到報文後,就創建起鏈接,這樣會致使不少無效鏈接的創建,大大的浪費了資源;
而客戶端接收到服務端發送的確認報文時,客戶端須要再發送報文確認是否要創建鏈接,而不是發送一次報文就創建起鏈接了;
那麼事實上真的是這樣嗎?
上面這種說法實際上是偏向於抽象的說法,而實際上還得從TCP的可靠性傳輸提及:
爲了實現可靠性傳輸,TCP通訊的雙方都必需要先維護一個初始化的序列號,標識當前發送TCP數據的序號,用於接收到TCP數據的主機判斷哪些數據是收到的,哪些是沒收到的;
而三次握手的過程是爲了告訴對方本身數據的起始
序列號
,和指望下次收到數據的確認序列號
,而一次握手,兩次握手都是不能實現這種操做的,若是是四次握手呢? 能夠,可是沒有必要,由於會浪費資源;
三次握手的目的就是爲了同步雙方的序列號,用於可靠性傳輸的保障,這個下面會講到;
具體以下所示:
揮手的意思,對於人類來講就是告別的含義,揮揮手不帶走一片雲彩。
而對於TCP鏈接來講, TCP鏈接斷開時,要斷開的兩臺主機會互相發送報文給對方,每發送一次報文就叫一次揮手;
假設有兩臺已經創建起鏈接的主機,分別爲主機A和主機B,主機A主動請求斷開鏈接;
第一次揮手:主機A會發送一個報文段(序列號seq=p,標誌位FIN=1),而後進入FIN-WAIT-1
狀態,發送了標誌位FIN=1以後,表示我要關閉這個鏈接,後續將不會再有數據傳輸過來,可是這時候主機A仍是能夠收到主機B發送過來的數據;
第二次揮手:主機B接受到主機A發送的FIN報文段,會發送一個確認報文段,標誌位ACK=1,確認序列號ack=p+1,而後就進入CLOSE-WAIT
狀態,這個過程表示接受到關閉方發送的關閉請求了。
這時候主機B就處於半關閉狀態,雖然主機A不會再發數據過來,可是主機B還可能會發數據給主機A;
主機A接收到確認報文後,會進入FIN-WAIT-2
狀態,而後等待主機B發送鏈接釋放報文;
第三次揮手:當主機B的數據都發送完畢後,就會想主機A發送釋放鏈接的報文,主機B發送FIN報文段,標誌位FIN=1,序列號seq=q,確認序列號p+1,標誌位ACK=1,而後就進入LAST-ACK
狀態;
第四次揮手:主機A接收到關閉報文段後,會發出確認報文段,標誌位ACK=1,確認序列號ack=q+1,序列號seq=u+1,而後進入TIME-WAIT
狀態,此時TCP鏈接尚未釋放,會等待2∗MSL(最長報文段壽命)的時間後,纔會進入CLOSED
狀態;
主機B接收到確認報文以後,纔會進入關閉狀態,至此,TCP鏈接結束,在此看來,接收關閉的主機TCP鏈接的關閉時間會更快一些。
爲何要等待2∗MSL以後,纔會進入關閉狀態呢?
MSL的全稱爲:Maximum Segment Lifetime
,翻譯過來的意思是:最長報文端壽命,表示報文在網絡上存在的最長時間,超過這個時間報文將被丟棄;
這個值是由當前主機設置,TCP容許設置爲不一樣的值;
主要的做用有兩個:
(1)保證客戶端發送的最後一個ACK報文可以到達服務器,由於這個ACK報文可能丟失
總結,雖然進行了4次揮手,可是作的操做不止四次;
揮手只是一個告知的消息,發送方和接收方都得作出響應操做;
請看流程圖:
上面咱們分析了TCP的四次揮手,那麼是否有這樣的疑問,爲何TCP鏈接斷開要進行四次揮手?
在分析爲何要四次揮手以前,咱們先來了解一下TCP鏈接的特性,TCP鏈接是全雙工通訊的;
全雙工通訊的意思是TCP鏈接的雙方均可以同時進行發送和接收消息,這個上面有講過;
由於TCP鏈接的雙方都能同時進行發送和接收消息,那麼要關閉鏈接的話,鏈接的雙方都要關閉,不能只關閉一方;
假設主機A和主機B正在進行TCP鏈接通訊,這時候主機A想斷開鏈接,那麼創建起鏈接的雙方都要關閉發送和接收通道,這僅僅發送一次報文的沒法實現的,主機A關閉本身的發送通道和接收通道,得進行兩個報文的發送,那麼主機B同理,也是得發送兩次報文來關閉本身的發送和接收通道;
那麼到這裏你是否就會有疑問?
我發送一次報文,就關閉本身的發送通道和接收通道不就好了,這樣TCP斷開鏈接只須要兩次揮手就能夠了,不是嗎?
固然理論上是能夠這樣作的,只要發送一次報文,就關閉本身的發送和接收通道,可是實際狀況爲何不是這樣作的呢,且聽我細細道來;
假如要斷開鏈接的主機A,發送一次TCP報文,告訴主機B我要斷開鏈接,而後就關閉本身的讀寫通道;
那麼這裏會致使什麼問題呢?
(1)關閉了寫的通道,表示我沒有數據要發送給主機B了,若是在網絡正常不丟包的狀況下,是能夠直接關閉寫的通道的,可是若是發送的這個數據丟包了,主機B沒有接收到這個報文,那麼主機B就認爲當前的鏈接有效,就繼續從主機A讀取數據,這樣會致使傳輸出現問題;
(2)關閉了讀的通道,表示我不讀取主機B發送過來的數據了,可是這時候並不肯定主機B是否還有沒有數據要發送過來,若是有數據要發送過來,而主機A卻關閉了讀的通道了,那麼也會致使傳輸出現問題;
既然無法發送一次TCP報文來關閉讀寫通道,那麼要怎麼作才能比較合理,比較符合TCP可靠傳輸的特色呢?
那麼接下來就要來說講前人智慧的結晶了;
假如讓你來設計一個關閉TCP鏈接的方案,你會怎麼設計呢?
首先咱們先來看一下TCP鏈接關閉的要求:
(1)TCP鏈接的主機雙方都要關閉讀寫通道;
(2)TCP鏈接的主機雙方都要保證數據的正常傳輸;
(3)要符合TCP可靠傳輸的特色;
那麼咱們知道了上面的要求,接下來來看看怎麼設計比較好呢?
既然不能一次性關閉讀和寫的通道,那麼咱們來分開進行關閉;
假設有兩臺正在進行TCP鏈接的主機,分別爲主機A和主機B,主機A要求要斷開鏈接;
(1)首先主機A先發送一次報文,告訴主機B,我要關閉寫的通道了,表示我沒有數據要發送給主機B了;
(2)這時候主機B有兩種狀況,一種狀況是正常收到了主機A發送的要關閉寫的通道的報文,另外一種狀況是沒有收到主機A發送的要關閉寫的通道的報文;
第一種狀況:當主機B收到報文時,知道了主機A不發送數據過來了,那麼主機B就關閉讀的通道,那麼這時候須要通知一下主機A,表示我已經收到你的報文了,否則的話主機A並不知道主機B到底收沒收到;
第二種狀況:主機B沒有收到報文,這時候主機A怎麼確認主機B是否收到了報文了,固然得要主機B告訴主機A才行,可是主機B沒有收到報文,就不會告訴主機A是否已經收到報文了,那麼主機A在發送了報文一段時間後,若是沒有收到主機B的迴應,那麼主機A就得再發送一次報文給主機B;
綜合上面兩種狀況,咱們知道,主機B收到報文後,必需要告訴主機A,我已經收到報文了,能夠不用再發送報文給我了;
那麼到這裏主機A能夠正常關閉寫的通道,主機B能夠正常關閉讀的通道;
主機A關閉了寫的通道後,尚未關閉讀的通道,而主機B關閉了讀的通道,尚未關閉寫的通道;
接下來咱們繼續分析:
(1)主機B在發送完全部數據後,發送報文告訴主機A,表示我這邊數據已經傳輸完畢,要關閉寫的通道了;
(2)這時候主機A也面臨着上面的這種狀況,一種是收到,一種是沒收到,我這裏就再也不多說了;
最後的狀況也是主機B發送報文給主機A,表示要關閉寫的通道,而主機A接收到報文後,必需要發送報文給主機B,表示我已經收到了,這個和上面的狀況同樣,這裏就再也不多說;
至此,TCP鏈接的雙方要正常的關閉,就必需要發送四次報文,也就是經典的四次揮手
;
我這裏只是講了大概的原理,實際狀況遠比這要複雜多,這其中還涉及到狀態機的變化,這個能夠看看上面四次揮手的分析👆;
TCP是基於IP層的協議來進行傳輸數據的,而IP層的協議是不靠譜的傳輸協議,那麼TCP協議是怎麼基於不靠譜的IP層協議來作到可靠傳輸的呢?
接下來讓咱們來看看他的真面目吧!
什麼是校驗和?
TCP校驗和(Checksum)是一個端到端的校驗和,由發送端計算出來,而後接收端進行驗證,用於校驗數據在發送前和發送後時候一致,若是接受方檢測到不一致了,則會丟棄該數據;
每個數據包都有序號,用於數據有序的傳輸,TCP在接收到數據後,會根據序號進行排序,而後再把數據交給應用層處理;
而主機接受到TCP數據後,必需要發送一個確認應答的TCP數據,用於表示我已經收到傳過來的數據了,序號是多少,而且告訴發送的主機下一次發送時,起始序號是多少;
如圖所示:
在進行TCP傳輸時,每次接受到數據後,都會給發送端返回一個確認應答,用於確認接收端已經接收到數據了;
可是實際上網絡是很不穩定的,數據發送了,接收端不必定就會接收到數據,或者接收端接收到了數據,可是確認報文發送端不必定能接收到;
主要有兩種狀況:
(1)發送端發送了數據,可是因爲延遲的問題,致使接收端遲遲沒有接收到數據;
(2)接收端接收到了數據,可是也是因爲網絡問題,致使發送端沒有接收到確認報文;
那麼這上面兩種狀況,TCP是怎麼來解決的呢?
TCP引入了一種叫超時重傳的機制,能夠理解爲,當數據發送了以後,通過一段時間,沒有收到響應,那麼就再從新發送一次數據給對方;
這裏的超時重傳機制是根據是否收到確認報文爲準的,也就是說上面兩種狀況均可以歸類爲一種狀況,就是發送端是否能夠接收到確認報文;
而報文的超時時間是動態計算的,由於網絡的複雜性,若是超時時間設置爲固定的,那麼有可能會形成超時時間過長或者太短的問題,而超時時間的計算是由一個嚴謹的算法來計算的,這裏就不過多深刻了;
感興趣的請參考:超時重傳的時間計算
(1)窗口
從傳輸的角度來看,咱們確定但願傳輸速度越快越好,那麼我是否能夠把全部數據都一次性發給對方呢?
很明顯是不能夠的,若是數據小的話可能不會有問題,可是若是數據量很大的狀況下呢,本身的發送緩存和對方的接收緩存是否能夠放得下這麼多數據呢,這種作法是不嚴謹的,而且很容易出錯,這並不符合TCP可靠性傳輸的特性;
那麼咱們怎麼來判斷要傳的數據的大小呢?
原理很簡單,就是由對方來告訴你,接收的一方來告訴發送方我能夠接收多大的數據而不會出錯;
那麼TCP是怎麼實現的呢?
經過TCP的窗口,這個在上面的TCP報文那裏有講過👆;
(2)傳輸效率
試想有一種狀況,當接收方的緩存已經滿了,而應用程序每次都只從TCP緩存中取出一個字節的數據,而後接收方就告訴發送方,我如今能夠接收一個字節的數據了,這樣會不會有問題呢?
一次傳輸一個字節的數據,雖然不會有什麼問題,可是對於傳輸的效率來講,效率過低了,一次傳輸只傳輸了一個字節的數據,會形成資源的浪費;
那麼要怎麼解決這種問題呢?
經過讓接收方多等待一端時間,等到接收緩存中的剩餘空間較多時,才發送確認報文,並帶上窗口信息來告訴發送方,能夠發送對應窗口大小的數據了,這樣就能夠避免傳輸效率的問題;
網絡的傳輸也是須要進行控制的,試想若是在網絡能接收傳輸的程度下,咱們無論不顧的往網絡中傳輸超過其能接受的程度,那麼就會形成網絡的阻塞;
好比一條高速公路,其能容納的車流量也是有限的,若是是正常的狀況下,高速公路是能夠正常運行,不會堵車的,可是若是在節假日放假的狀況下,一大堆車會涌向高速公路,而這時候超過了高速公路所能容納的流量,就會形成堵車,而網絡的狀況也是如此;
擁塞控制和流量控制不同,擁塞控制是做用於網絡,用於控制網絡中傳輸的效率,而流量控制是做用於接收方;
常見的擁塞控制有:
(1)慢開始,擁塞避免(2)快重傳,快恢復
擁塞控制的算法有哪些呢?
(1)慢開始算法
發送方維持一個叫作擁塞窗口cwnd(congestion window)的狀態變量,而這個窗口的大小是根據網絡的擁塞程度來動態變化的;
擁塞窗口的大小取決於網絡的擁塞程度,而且會根據擁塞程度來進行動態的變化,發送方的發送窗口等於擁塞窗口的大小,而還要考慮到接收方的流量控制窗口,那麼可能會出現發送窗口小於擁塞窗口的狀況;
而慢開始算法的實現原理就是,一開始向網絡發送一個很小的數據包,用於探測網絡的擁塞程度,然後再動態的加倍增長,直到達到網絡所能接受的程度而不形成網絡擁塞;
(2)擁塞避免算法
擁塞避免算法的原理就是,每次在發送數據包的時候,只增長很小的窗口容量,好比cwnd加1,而不是加倍的增長;
而上面的慢開始的算法若是每次都進行加倍的增長,就會很容易出現網絡擁塞的狀況,這樣就沒法計算的很精準的擁塞窗口容量;
那麼咱們能夠把慢開始算法和擁塞避免算法結合,若是慢開始算法加倍後,出現了網絡擁塞,那麼就把以前加倍的去掉,而後再採用擁塞避免算法,逐漸的遞增,來試探網絡的擁塞窗口大小;
擁塞的程度判斷,通常都是經過有沒有接收到確認報文,固然可能其餘狀況也會致使沒有接受到確認報文,可是其餘狀況都是統一當成擁塞的狀況處理了;
擁塞避免算法並非能夠百分百的避免網絡擁塞,而是會下降出現網絡擁塞出現的機率;
(3)快重傳算法
快重傳算法的實現原理是,要求接收方在接收到一個失序的數據後,就馬上發出重複確認報文,而不是要等到發送數據的時候捎帶確認報文,這樣可使發送方及早的知道有哪些報文沒有接收到;
(4)快恢復算法
快恢復算法的實現原理的是,當進行了快重傳算法時,發送方接收到了重複的確認報文,而這時候就認爲網絡尚未處於擁塞的狀況,那麼就將當前傳輸速度減半後,不走慢開始算法;
由於網絡沒有處於擁塞的狀況,那麼就執行擁塞避免算法,使cwnd緩慢增大,讓網絡傳輸速度快速恢復;
綜上所訴,總結爲以下流程圖:
ssthresh:慢開始門限
cwnd:擁塞窗口
至於鏈接管理,那就是著名的三次握手和四次揮手機制,這個上面已經講的很詳細了👆,這裏就不重複講了;
UDP包頭格式沒有TCP那麼複雜,由於UDP傳輸是不可靠的,就沒有TCP那麼多機制;
和TCP相比,UDP的包頭就很簡單了;
發送數據前不須要創建鏈接,那麼發送結束以後也不須要釋放鏈接,速度較快;
UDP傳輸盡最大的努力傳輸,可是並不保證可靠性傳輸,不須要維持鏈接的狀態;
發送方的UDP將應用程序交付下來的報文,直接添加首部後,就交給IP層了;
對於應用程序交付下來的報文,不進行拆分,也不合並,應用程序傳啥,那麼UDP就傳啥;
即便網絡出現擁塞了,也不進行擁塞控制,對於一些須要實時性的應用程序,並不須要考慮網絡的擁塞;
好比直播,或者遊戲等軟件,能夠容許網絡丟包,可是對於傳輸的實時性要求較高;
支持一對一,一對多,多對一,多對多等通訊;
首部只有8個字節,比TCP的20個字節的首部要短;
(1)網頁或者APP的訪問
訪問網頁和手機 APP 都是基於 HTTP 協議的。HTTP 協議是基於 TCP 的,創建鏈接都須要屢次交互,對於不穩定的網絡環境來說,創建一次鏈接須要的時間會比較長,然而既然是移動中,TCP 可能還會斷了重連,也是很耗時的。
而QUIC(全稱 Quick UDP Internet Connections,快速 UDP 互聯網鏈接)是Google基於UDP改進的一種通訊協議,旨在減小數據傳輸及建立連線時的延遲時間,雙向控制帶寬,以免網絡擁塞;
(2)流媒體的協議
多用於直播方面的視頻傳輸協議,好比上面提到的QUIC協議;
(3)實時遊戲
對於遊戲來講,實時性的操做很是重要,而對於UDP來講,實時性正是其特色;
(4)物聯網
TCP對於物聯網來講,維護的成本較高,而UDP對於物聯網的實時性來講,是很是適合的; 好比CoAP協議,就是基於 UDP 協議的;
TCP報文段首部格式詳解
傳輸控制協議
socket是什麼?套接字是什麼
TCP流量控制、擁塞控制
快速UDP網絡鏈接
簡單理解Socket
tcp udp流程圖
兩張動圖-完全明白TCP的三次握手與四次揮手
TCP 爲何三次握手而不是兩次握手(正解版)
《計算機網絡》
極客時間-趣談網絡協議-第10講