Android 網絡編程之TCP、UDP詳解

本章目錄

  • 一、TCP,UDP是什麼?
  • 二、傳輸層
  • 三、TCP鏈接的特色有哪些?
  • 四、TCP包頭格式
  • 五、TCP狀態機
  • 六、三次握手?
  • 七、四次揮手?
  • 八、TCP鏈接是怎麼保證可靠性的?
  • 九、UDP包頭格式是啥?
  • 十、UDP鏈接的特色有哪些?
  • 十一、UDP鏈接的使用場景有哪些?

本章結構圖

一、TCP,UDP是什麼?

1.一、爲何要進行網絡分層?

在上一篇文章裏講到了網絡的分層,提到了TCP/IP組模型,html

以下:git

可是是否有這樣的疑問,爲何網絡要進行分層呢?github

計算機網絡是一個很是複雜的系統,要想在其中兩臺主機創建鏈接,必需要考慮很是多的場景,假如咱們要在兩臺主機之間傳送一個文件,那麼咱們須要考慮的方法具體有下面幾點:web

  • (1)線路:首先發起通信的主機必需要先激活傳送的通信線路,保證要傳送的數據在這條線路上能夠正常的發送和接受;
  • (2)接收主機:要告訴網絡數據要發送到哪臺主機去;
  • (3)確保到達:發起通信的主機要確保接受的主機是否已開機,是否處於正常工做狀態;
  • (4)確保接收文件:發起通信的主機要確保對方主機是否已經作好接受和處理文件的準備工做;
  • (5)確認文件格式:確保接收的主機是否已經作好能夠處理這種文件格式的準備,若是沒有的話,兩個主機之間必須有一臺能夠處理文件轉換;
  • (6)確保數據正常到達:傳送過程當中若是遇到異常請求,好比丟包,網絡異常,傳送錯誤,重複等狀況,要保證數據能夠正常傳送到接收的主機,就必須得要有各類各樣的容錯處理;

這裏只列舉了大概幾種狀況,還有其餘不少場景要處理,我這裏就不一一列出來了;算法

從這裏能夠看出,就只是一個文件的傳遞,都須要考慮這麼多場景,可想而知,計算機網絡是何其的複雜;緩存

那麼既然有這些問題存在,讓咱們試想着如何去解決這種問題;服務器

既然場景這麼多,那麼咱們能不能將這些場景進行歸類,而後進行分層,每一類場景交由某個類別去進行處理呢?網絡

答案是:能夠的;socket

上面這個文件的傳送,咱們能夠歸類爲三層:文件傳輸,通信服務,網絡接入這幾層;tcp

看一下大概的流程圖:

固然上面只是咱們的假想,實際上的模塊劃分遠比這個複雜的多;

好比最開始的OSI模型,足足分了七層;

到這裏你是否有疑問了,這樣進行分層的好處有哪些呢?請看下面;

分層的好處:

  • (1) 每一層是相對獨立的,只須要處理本身負責的模塊就行,經過將相對複雜的問題,分解爲幾部分小的問題,交由對於的模塊去處理,以此來解決複雜的問題;
  • (2) 靈活性好,若是某一層邏輯發生變更,只要其對外開放的接口沒有發生改變,就不會影響到其餘層面的工做,模塊之間相對比較靈活;
  • (3) 結構能夠分割開,每一層均可以採用比較適合本身的數據,沒必要考慮其餘模塊的影響;
  • (4) 易於實現和維護,若是某一層須要修改什麼東西,只要其對外開放的接口沒有改變,那麼其修改就不會影響到其餘層的工做,由於模塊之間耦合性低;
  • (5) 可以提供精準化服務,每一層的職責都很明確,都會提供相應的服務;

1.二、TCP,UDP是什麼?

TCP(傳輸控制協議)和UDP(用戶數據報協議)是傳輸層的協議,基於網絡層IP協議來實現的;

TCP協議爲兩個主機的通信提供可靠性傳輸,經過將數據切分爲適合傳輸的大小,使用超時重傳,確認到達等一系列操做來保證數據能夠準確的進行傳輸;因爲提供了端到端的可靠性傳輸,應用層的軟件就不須要關心傳輸的相關細節了;

UDP協議提供簡單快速的數據傳送,可是不保證數據的準確性,穩定性,所以使用這個協議的應用層的軟件須要考慮穩定性和準確性的問題;

二、傳輸層

2.一、傳輸層是怎麼工做的?

應用程序在通信的時候,須要先創建起鏈接,而創建鏈接的基礎須要先標誌本身的進程id,也就是PID,若是隻是本地通信的話,PID基本上不會有衝突,可是和網絡上的其餘主機通信時,PID的衝突概率就會大大增長;

那麼要怎麼解決這個問題呢?

咱們知道IP層的協議的IP地址在網絡中是惟一的,不會和其餘主機衝突,那麼咱們能夠利用這個來避免端口號衝突,也就是IP地址+端口號的實現;

而這種標識就是socket通信,最終的格式:Socket=(IP地址:端口號);

2.二、socket是什麼?

socket翻譯過來的意思就是插座,用於應用程序經過網絡進行通信,也被稱爲套接字;

套接字能夠看出是兩個應用程序經過傳輸層傳輸數據時,使用的端點,而套接字是一個抽象的概念,具體實現是由計算機來實現的;

好比當前主機要和另一臺主機進行數據的傳輸,會先將數據寫入到socket中,而後經過傳輸層傳輸到另一臺主機的socket中,而後應用程序再從socket中讀取數據;

2.三、socketAPI函數

socket是"打開—讀/寫—關閉"的實現模式,具體實現以下:

  • socket():根據地址類型,socket類型,協議類型建立socket;
  • bind():通常用於服務端,給socket綁定IP地址和端口號;
  • listen():用於服務端,監聽該端口的請求;
  • accept():用於服務端,接收來自客戶端的鏈接請求;
  • connect():用於客戶端,鏈接指定計算機的端口;
  • send()/recv():從socket中讀取和發送數據;
  • close():關閉socket;
  • gethostbyname()和gethostbyaddr():用於解析主機名和地址。
  • select():用於修整有以下狀況的套接字列表: 準備讀,準備寫或者是有錯誤。
  • poll():用於檢查套接字的狀態。 套接字能夠被測試,看是否能夠寫入、讀取或是有錯誤。
  • getsockopt() 用於查詢指定的套接字一個特定的套接字選項的當前值。
  • setsockopt() 用於爲指定的套接字設定一個特定的套接字選項。

2.四、socket在TCP的基本流程

2.五、socket在UDP的基本流程

三、TCP鏈接的特色有哪些?

3.一、面向鏈接

TCP是面向鏈接的協議,也就是在進行通訊以前,必須先創建起鏈接,通訊完以後,必需要釋放鏈接;

3.二、點對點

每條TCP鏈接只能有兩個端點,不能一對多,或者多對一,只能一一對應,不支持多播(multicast)和廣播(broadcast)的傳輸方式;

3.三、可靠交付

TCP提供可靠交付,保證數據不出錯,不重複,不丟失而且有序的傳達給對方;

3.四、全雙工通訊

TCP通訊的雙方均可以同時向對方發送數據和接收對方發送的數據,而且在本地設置有發送緩存和接收緩存,用於應用程序發送數據和取數據,這樣應用程序就不用關心數據的發送和接收了,只須要將數據交給傳輸層便可;

3.五、面向字節流

流:指的是流入到進程或者從進程流出的字節序列;

應用程序將要傳輸的數據寫入到TCP的發送緩存中,而後TCP再根據實際傳輸,從發送緩存取出必定的字節序列來進行傳輸,而另外一端接收到數據後,會將數據放入到接收緩存中,應用程序再從接收緩存中讀取字節數據;

這其中,應用程序寫入發送緩存的字節序列並不表明就是TCP要發送的字節序列,TCP會將發送緩存中的字節序列拆分紅適合傳輸的序列來進行傳輸;

這個圖只講了大概的流程,實際上數據還得經過IP層和數據鏈路層的封裝才能進行傳輸;

四、TCP包頭格式是啥?

4.一、先來看一下TCP數據的結構:

4.二、看一下TCP首部報文段的結構圖:

  • (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狀態機

5.一、TCP狀態機是什麼?

TCP狀態機是指網絡通訊過程當中,狀態變化的狀況;

在TCP通訊的三次握手和四次揮手的過程當中,就是TCP狀態變化的過程,因爲TCP是面向鏈接的,具備可靠性的鏈接,每個要通訊的主機都得和對方創建起鏈接,而這過程會經歷鏈接,傳輸,關閉這幾個步驟,在雙方進行通訊的過程,TCP的狀態變化是不同的;

5.二、TCP狀態有哪些?

  • LISTEN:監聽來自其餘主機的TCP端口的請求;
  • SYN_SENT:發送鏈接請求後,等待確認鏈接請求;
  • SYN-RECEIVED:收到鏈接請求後,等待確認創建鏈接請求;
  • ESTABLISHED:表示鏈接已經創建起來,能夠進行數據傳輸了;
  • FIN_WAIT_1:等待遠程TCP鏈接中斷請求或者先前的中斷請求的確認;
  • FIN_WAIT_2:等待來自遠程TCP鏈接的中斷請求;
  • CLOSE_WAIT:該端點已經收到遠程端點的中斷請求,等待本地應用程序的鏈接中斷請求;
  • CLOSING:等待來自遠程TCP的終止請求的確認;
  • LAST_ACK:等待以前發送到遠程TCP的鏈接終止請求的確認;
  • TIME_WAIT:等待足夠的時間確保遠程TCP接受到鏈接中斷請求的確認;
  • CLOSED:沒有任何鏈接狀態;

來看一下《計算機網絡》關於狀態機的流程圖:

至於狀態機的變化,咱們下面的三次握手和四次揮手會講到;

六、三次握手

6.一、什麼是握手?

對於人類來講,握手錶示雙方友好交互的意思;而對於計算機來講,握手的意義就大不相同了;

來看一下wiki對於計算機握手的定義:

意思就是:在信息傳輸以前,握手用於確認參數和其餘協議特性達成一致;

而對於tcp的握手來講,是兩臺主機之間互相交換一次tcp數據,用於確認參數和序列;每一次握手,主機都得向對方發送一次tcp數據;

6.二、三次握手是什麼?

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鏈接成功創建;

看一下流程圖:

6.三、爲何是三次握手?

讓我引用《計算機網絡》一書上的說法:

爲了防止已經失效的鏈接請求報文段忽然又傳到服務端,於是產生錯誤;

對於這句話的解讀:

對於從客戶端發送到服務端的請求鏈接的報文,由於網絡上的延遲,或者阻塞等緣由,致使鏈接已經釋放後再被服務端接收到,此時服務端再給客戶端發送報文表示鏈接創建成功;

這時候發送給服務端的報文有多是已經失效的報文了,而服務器在接收到報文後,就創建起鏈接,這樣會致使不少無效鏈接的創建,大大的浪費了資源;

而客戶端接收到服務端發送的確認報文時,客戶端須要再發送報文確認是否要創建鏈接,而不是發送一次報文就創建起鏈接了;

那麼事實上真的是這樣嗎?

上面這種說法實際上是偏向於抽象的說法,而實際上還得從TCP的可靠性傳輸提及:

爲了實現可靠性傳輸,TCP通訊的雙方都必需要先維護一個初始化的序列號,標識當前發送TCP數據的序號,用於接收到TCP數據的主機判斷哪些數據是收到的,哪些是沒收到的;

而三次握手的過程是爲了告訴對方本身數據的起始序列號,和指望下次收到數據的確認序列號,而一次握手,兩次握手都是不能實現這種操做的,若是是四次握手呢? 能夠,可是沒有必要,由於會浪費資源;

三次握手的目的就是爲了同步雙方的序列號,用於可靠性傳輸的保障,這個下面會講到;

具體以下所示:

七、四次揮手

7.一、什麼是揮手?

揮手的意思,對於人類來講就是告別的含義,揮揮手不帶走一片雲彩。

而對於TCP鏈接來講, TCP鏈接斷開時,要斷開的兩臺主機會互相發送報文給對方,每發送一次報文就叫一次揮手;

7.二、四次揮手是什麼?

假設有兩臺已經創建起鏈接的主機,分別爲主機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次揮手,可是作的操做不止四次;

揮手只是一個告知的消息,發送方和接收方都得作出響應操做;

請看流程圖:

7.三、爲何是四次揮手?

上面咱們分析了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鏈接是怎麼保證可靠性的?

TCP是基於IP層的協議來進行傳輸數據的,而IP層的協議是不靠譜的傳輸協議,那麼TCP協議是怎麼基於不靠譜的IP層協議來作到可靠傳輸的呢?

接下來讓咱們來看看他的真面目吧!

8.一、校驗和

什麼是校驗和?

TCP校驗和(Checksum)是一個端到端的校驗和,由發送端計算出來,而後接收端進行驗證,用於校驗數據在發送前和發送後時候一致,若是接受方檢測到不一致了,則會丟棄該數據;

8.二、確認應答與序號

每個數據包都有序號,用於數據有序的傳輸,TCP在接收到數據後,會根據序號進行排序,而後再把數據交給應用層處理;

而主機接受到TCP數據後,必需要發送一個確認應答的TCP數據,用於表示我已經收到傳過來的數據了,序號是多少,而且告訴發送的主機下一次發送時,起始序號是多少;

如圖所示:

8.三、超時重傳

在進行TCP傳輸時,每次接受到數據後,都會給發送端返回一個確認應答,用於確認接收端已經接收到數據了;

可是實際上網絡是很不穩定的,數據發送了,接收端不必定就會接收到數據,或者接收端接收到了數據,可是確認報文發送端不必定能接收到;

主要有兩種狀況:

(1)發送端發送了數據,可是因爲延遲的問題,致使接收端遲遲沒有接收到數據;
(2)接收端接收到了數據,可是也是因爲網絡問題,致使發送端沒有接收到確認報文;

那麼這上面兩種狀況,TCP是怎麼來解決的呢?

TCP引入了一種叫超時重傳的機制,能夠理解爲,當數據發送了以後,通過一段時間,沒有收到響應,那麼就再從新發送一次數據給對方;

這裏的超時重傳機制是根據是否收到確認報文爲準的,也就是說上面兩種狀況均可以歸類爲一種狀況,就是發送端是否能夠接收到確認報文;

而報文的超時時間是動態計算的,由於網絡的複雜性,若是超時時間設置爲固定的,那麼有可能會形成超時時間過長或者太短的問題,而超時時間的計算是由一個嚴謹的算法來計算的,這裏就不過多深刻了;

感興趣的請參考:超時重傳的時間計算

8.四、流量控制

(1)窗口

從傳輸的角度來看,咱們確定但願傳輸速度越快越好,那麼我是否能夠把全部數據都一次性發給對方呢?

很明顯是不能夠的,若是數據小的話可能不會有問題,可是若是數據量很大的狀況下呢,本身的發送緩存和對方的接收緩存是否能夠放得下這麼多數據呢,這種作法是不嚴謹的,而且很容易出錯,這並不符合TCP可靠性傳輸的特性;

那麼咱們怎麼來判斷要傳的數據的大小呢?

原理很簡單,就是由對方來告訴你,接收的一方來告訴發送方我能夠接收多大的數據而不會出錯;

那麼TCP是怎麼實現的呢?

經過TCP的窗口,這個在上面的TCP報文那裏有講過👆;

(2)傳輸效率

試想有一種狀況,當接收方的緩存已經滿了,而應用程序每次都只從TCP緩存中取出一個字節的數據,而後接收方就告訴發送方,我如今能夠接收一個字節的數據了,這樣會不會有問題呢?

一次傳輸一個字節的數據,雖然不會有什麼問題,可是對於傳輸的效率來講,效率過低了,一次傳輸只傳輸了一個字節的數據,會形成資源的浪費;

那麼要怎麼解決這種問題呢?

經過讓接收方多等待一端時間,等到接收緩存中的剩餘空間較多時,才發送確認報文,並帶上窗口信息來告訴發送方,能夠發送對應窗口大小的數據了,這樣就能夠避免傳輸效率的問題;

8.五、擁塞控制

網絡的傳輸也是須要進行控制的,試想若是在網絡能接收傳輸的程度下,咱們無論不顧的往網絡中傳輸超過其能接受的程度,那麼就會形成網絡的阻塞;

好比一條高速公路,其能容納的車流量也是有限的,若是是正常的狀況下,高速公路是能夠正常運行,不會堵車的,可是若是在節假日放假的狀況下,一大堆車會涌向高速公路,而這時候超過了高速公路所能容納的流量,就會形成堵車,而網絡的狀況也是如此;

擁塞控制和流量控制不同,擁塞控制是做用於網絡,用於控制網絡中傳輸的效率,而流量控制是做用於接收方;

常見的擁塞控制有:
(1)慢開始,擁塞避免(2)快重傳,快恢復

擁塞控制的算法有哪些呢?

(1)慢開始算法

發送方維持一個叫作擁塞窗口cwnd(congestion window)的狀態變量,而這個窗口的大小是根據網絡的擁塞程度來動態變化的;

擁塞窗口的大小取決於網絡的擁塞程度,而且會根據擁塞程度來進行動態的變化,發送方的發送窗口等於擁塞窗口的大小,而還要考慮到接收方的流量控制窗口,那麼可能會出現發送窗口小於擁塞窗口的狀況;

而慢開始算法的實現原理就是,一開始向網絡發送一個很小的數據包,用於探測網絡的擁塞程度,然後再動態的加倍增長,直到達到網絡所能接受的程度而不形成網絡擁塞;

(2)擁塞避免算法

擁塞避免算法的原理就是,每次在發送數據包的時候,只增長很小的窗口容量,好比cwnd加1,而不是加倍的增長;

而上面的慢開始的算法若是每次都進行加倍的增長,就會很容易出現網絡擁塞的狀況,這樣就沒法計算的很精準的擁塞窗口容量;

那麼咱們能夠把慢開始算法和擁塞避免算法結合,若是慢開始算法加倍後,出現了網絡擁塞,那麼就把以前加倍的去掉,而後再採用擁塞避免算法,逐漸的遞增,來試探網絡的擁塞窗口大小;

擁塞的程度判斷,通常都是經過有沒有接收到確認報文,固然可能其餘狀況也會致使沒有接受到確認報文,可是其餘狀況都是統一當成擁塞的狀況處理了;

擁塞避免算法並非能夠百分百的避免網絡擁塞,而是會下降出現網絡擁塞出現的機率;

(3)快重傳算法

快重傳算法的實現原理是,要求接收方在接收到一個失序的數據後,就馬上發出重複確認報文,而不是要等到發送數據的時候捎帶確認報文,這樣可使發送方及早的知道有哪些報文沒有接收到;

(4)快恢復算法

快恢復算法的實現原理的是,當進行了快重傳算法時,發送方接收到了重複的確認報文,而這時候就認爲網絡尚未處於擁塞的狀況,那麼就將當前傳輸速度減半後,不走慢開始算法;

由於網絡沒有處於擁塞的狀況,那麼就執行擁塞避免算法,使cwnd緩慢增大,讓網絡傳輸速度快速恢復;

綜上所訴,總結爲以下流程圖:

ssthresh:慢開始門限

cwnd:擁塞窗口

8.6 鏈接管理

至於鏈接管理,那就是著名的三次握手四次揮手機制,這個上面已經講的很詳細了👆,這裏就不重複講了;

九、UDP包頭格式是啥?

UDP包頭格式沒有TCP那麼複雜,由於UDP傳輸是不可靠的,就沒有TCP那麼多機制;

和TCP相比,UDP的包頭就很簡單了;

  • (1) 源端口號和目標端口號:每一個TCP段都包含源端口號和目標端口號,用於確認TCP數據的來源和要發送的端口號,而計算機上的程序是經過監聽端口號來獲取TCP數據包的;
  • (2) 校驗和:用於TCP數據的校驗,是TCP傳輸可靠性的保障之一,由發送端填充,接收端進行校驗;

十、UDP鏈接的特色有哪些?

10.一、面向無鏈接

發送數據前不須要創建鏈接,那麼發送結束以後也不須要釋放鏈接,速度較快;

10.二、儘可能交付

UDP傳輸盡最大的努力傳輸,可是並不保證可靠性傳輸,不須要維持鏈接的狀態;

10.三、面向報文

發送方的UDP將應用程序交付下來的報文,直接添加首部後,就交給IP層了;

對於應用程序交付下來的報文,不進行拆分,也不合並,應用程序傳啥,那麼UDP就傳啥;

10.四、沒有擁塞控制

即便網絡出現擁塞了,也不進行擁塞控制,對於一些須要實時性的應用程序,並不須要考慮網絡的擁塞;

好比直播,或者遊戲等軟件,能夠容許網絡丟包,可是對於傳輸的實時性要求較高;

10.五、靈活性高

支持一對一,一對多,多對一,多對多等通訊;

10.六、首部開銷小

首部只有8個字節,比TCP的20個字節的首部要短;

十一、UDP鏈接的使用場景有哪些?

(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講

其餘

Android 你不得不學的HTTP相關知識

關於我

兄dei,若是個人文章對你有幫助的話,請幫我點個贊吧️,也能夠關注一下個人Github博客;

相關文章
相關標籤/搜索