淺談網絡-UDP與TCP

提到UDP和TCP,可能大家並不陌生,多少這兩個協議也是混的耳熟,在面試啊什麼的場景下提問的話,一般都會問這兩者的區別,大部分人都會回答,首先他們是基於傳輸層的,TCP是面向連接的,是可信的,UDP是面向無連接的,是不可信的。那麼什麼是面向連接的,什麼是面向無連接呢?還有就是爲什麼他們回可信和不可信呢?如果說三次握手的話,那我UDP也發三個包進行嘗試,這樣有區別嗎?接下來咱們就進行討論分析下。

一.TCP和UDP的區別

TCP是面向連接的,UDP是面向無連接的。要了解兩者的區別,首要需要了解的是什麼是面向連接/無連接?所謂的建立連接,是指客戶端和無服務爲了維護連接,建立的一定的數據結構來維護雙方的交互狀態,用這兩的數據結構來保證所謂的面向連接的特性。

1.TCP提供可靠的數據傳輸,而UDP可能會丟包,不保證數據包會按順序到達。
2.TCP是面向字節流的,發送的時候是一個流,無頭無尾,而UDP是基於數據報的,一個個的發,一個個的接受。
3.TCP是有擁塞控制的,而UDP沒有
4.TCP是一個有狀態服務,也就是說可知道哪些發了,都接受了沒有,而UDP是無狀態服務,發了就發了

基本來了解了這些區別後,咱們來分別去了解下這兩個協議各自的特性,然後對比來知道各自的特徵。

二.UDP

首先說UDP,UDP的話是繼承與IP協議的,所以也就代表着它的特徵更加的近似於IP協議,接下來咱們講一下他的特點,用途等,幫助更容易的瞭解它。

1.UDP報文

2.UDP的三大特點

UDP協議相對簡單,有以下幾個特點:

第一,溝通簡單,沒有大量的數據結構,處理邏輯等。不回去檢查網絡環境,默認很容易到達的情況,數據包不容易丟失。

第二,不會建立端到端的連接,只要是向堅挺端口發送包,都會被一視同仁的接受,可以接受任何人發來的數據,也可以傳給任何人。

第三,沒有擁塞控制等,無論當前網絡環境是怎樣的,當有發包的需求的時候,就會發出,不會根據網絡擁塞情況,丟包情況進行自主調節。

3.UDP的三大應用場景

基於UDP以上的幾個特點,一般會在如下幾個場景下進行使用。

第一,需要資源少,網絡情況比較好並且對於丟包不敏感的應用。例如DHCP就是基於UDP進行實現的,一般獲取IP地址都是內網請求,網絡環境相對較好,並且就算是當時一次兩次獲取不到IP也沒什麼關係,過後重新獲取即可。

第二,不需要進行一對一建立連接的,可以廣播的應用。對於多播這種情景,可能參考“組播”的概念(IP地址中有一個D類地址,就是組播地址,可以講包組播給一批設備),使用案例的話,我記得有個協議VXLAN,有興趣的可以去了解下。「一定要注意的是,ARP協議在應用上也是廣播,但是是在網絡層的協議,UDP是傳輸層的,ARP不是基於UDP的」

第三,處理速度快,延時低。當前很多應用都是要求低延時的,丟包的話丟就丟了,沒必要重新傳,網絡延遲大的話也要正常發出這樣的情況。例如很多即時對戰的遊戲就使用UDP,像LOL啊啥的,丟就丟了,但是時延是不能容忍的,當然現在的直播啊,物聯網呀這些也大都是選擇UDP的。

三.TCP

大體瞭解了UDP後,接下來咱們來談談TCP。與UDP不同,TCP默認網絡環境是差的,不可信的,所以就會使用一定的算法,來保證傳說的可靠性。

1.TCP報文

對比來看UDP的報文樣式,可知道TCP的報文中多處了很多東西,例如序號,確認序號,窗口大小等,那這些都是幹什麼的呢?

包的序號是爲了解決亂序的問題。確認哪個應該先來,哪個應該後到。

確認序號是將包發出去後,回包說已經確認到達的數據。確認哪些需要補發。

TCP首部中有6個標誌比特,它們中的多個可同時被設置爲1,主要是用於操控TCP的狀態機的,依次爲URG,ACK,PSH,RST,SYN,FIN。時序圖的時候需要用到,意義如下:

URG:此標誌表示TCP包的緊急指針域(後面馬上就要說到)有效,用來保證TCP連接不被中斷,並且督促中間層設備要儘快處理這些數據;

ACK:此標誌表示應答域有效,就是說前面所說的TCP應答號將會包含在TCP數據包中;有兩個取值:0和1,爲1的時候表示應答域有效,反之爲0;

PSH:這個標誌位表示Push操作。所謂Push操作就是指在數據包到達接收端以後,立即傳送給應用程序,而不是在緩衝區中排隊;

RST:這個標誌表示連接復位請求。用來複位那些產生錯誤的連接,也被用來拒絕錯誤和非法的數據包;

SYN:表示同步序號,用來建立連接。SYN標誌位和ACK標誌位搭配使用,當連接請求的時候,SYN=1,ACK=0;連接被響應的時候,SYN=1,ACK=1;這個標誌的數據包經常被用來進行端口掃描。掃描者發送一個只有SYN的數據包,如果對方主機響應了一個數據包回來 ,就表明這臺主機存在這個端口;但是由於這種掃描方式只是進行TCP三次握手的第一次握手,因此這種掃描的成功表示被掃描的機器不很安全,一臺安全的主機將會強制要求一個連接嚴格的進行TCP的三次握手;

FIN: 表示發送端已經達到數據末尾,也就是說雙方的數據傳送完成,沒有數據可以傳送了,發送FIN標誌位的TCP數據包後,連接將被斷開。這個標誌的數據包也經常被用於進行端口掃描。

窗口大小主要作用是來限制傳輸的速度。不要一次性發送大量數據,處理不過來,也不要太少,不夠處理資源浪費。就是之前說的擁塞控制。是根據發包情況來計算得到的。

2.經典的三次握手

不得不說的是,每次說到TCP協議,一定要講的就是這三次握手,TCP連接的建立,我們稱之爲三次握手,這是保證TCP協議可靠特性的保障。「要注意的是,三次握手除了雙方建立連接外,主要還是爲了溝通一件事情,就是TCP 包的序號的問題。」

一開始,客戶端和服務端都處於 CLOSED 狀態。先是服務端主動監聽某個端口,處於 LISTEN 狀態。然後客戶端主動發起連接 SYN,之後處於 SYN-SENT 狀態。服務端收到發起的連接,返回 SYN,並且 ACK 客戶端的 SYN,之後處於 SYN-RCVD 狀態。客戶端收到服務端發送的 SYN 和 ACK 之後,發送 ACK 的 ACK,之後處於 ESTABLISHED 狀態,因爲它一發一收成功了。服務端收到 ACK 的 ACK 之後,處於 ESTABLISHED 狀態,因爲它也一發一收了。

3.四次揮手

三次握手是建立可信連接的時候很重要的手段,那麼斷開連接的時候,爲什麼也要四次揮手這麼複雜的流程?這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的連接請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可能未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。

「注意,在四次揮手的時候會設置MSL(報文最大生存時間),超過設置時長後會被丟棄」

4.TCP狀態機

裏面每個步驟概念可能較爲複雜,將連接建立和連接斷開的兩個時序狀態圖綜合起來,就是這個著名的 TCP 的狀態機。學習的時候比較建議將這個狀態機和時序狀態機對照着看,會事半功倍。

下圖中,加黑加粗的部分,是上面說到的主要流程,其中阿拉伯數字的序號,是連接過程中的順序,而大寫中文數字的序號,是連接斷開過程中的順序。加粗的實線是客戶端 A 的狀態變遷,加粗的虛線是服務端 B 的狀態變遷。

5.TCP傳輸策略

TCP是如何傳輸的呢?TCP爲了保證順序性會給每個傳輸包一個編號ID,在建立連接的時候就會商定好,傳輸是從哪個ID開始,然後按照標號ID一個一個的進行順序傳輸。傳輸完成後會有應答,不過需要注意的是,這裏的應答不會是收到了哪個包,而是收到了哪個ID以前的所有包。這種應答被稱爲累計應答。那麼就會引申下來,發送端發送緩存情況和接收端接受情況會在各自存儲中分別記錄。

發送端的話會被分爲4部分:發送了已確認的;發送了待確認的;沒有發送的,等待發送的;沒有發送的,暫不發送的。如下圖示例:


其中LastByteAcked代表第一部分和第二部分分割;LastByteSent代表第二和第三部分分割;AdvertusedWindow是指的窗口大小(報文那裏提到的限制傳輸的速度的那個窗口),在圖中是加粗的黑框,黑框的大小來源於接受端處理能力,框內爲第三部分,框外爲第四部分。

接受端的話會被分爲三部分:接受並已確認過的;還沒有接受,可處理的;還沒有接受,超出處理範圍的。如下圖所示:


其中LastByteRead代表已經接受了,但是未被應用層讀取的;NextByteExpected是第一部分和第二部分分割線;MaxRcvBuffer是最大緩存量;窗口大小基本計算AdvertisedWindow=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead)。「要注意的是,發送端的窗口大小是取決與接受端處理能力,控制這我們的流量大小和擁塞情況,當然後面也有了TCP 擁塞控制的 BBR擁塞算法,都會影響窗口的大小,不僅僅是上面那個公式那麼簡單」

這兩個圖中,可以得到的信息是,123 發送並接受成功來;45接受成功的回包沒收到,應該是回報在路上或者丟了;6789發送了,先收到了89,67在路上或者丟了,位置給他們預留着。那麼怎麼判斷包是丟了還是在路上呢?這裏就用到了超時重發,也就是對每個包都設置一個定時器,超過了這個時間就進行重發。那麼這個時間是怎麼來的呢?這裏用到了自適應重傳算法,即是估計往返時間,過程是, TCP 通過採樣 RTT 的時間,然後進行加權平均,算出一個值,而且這個值還是要不斷變化的,因爲網絡狀況不斷的變化。除了採樣 RTT,還要採樣 RTT 的波動範圍,計算出一個估計的超時時間。「需要注意的是:TCP 對於超時重傳的包的策略是超時間隔加倍。每當遇到一次超時重傳的時候,都會將下一次超時時間間隔設爲先前值的兩倍。兩次超時,就說明網絡環境差,不宜頻繁反覆發送。」,以下是超時衝出按具體過程:

一條 TCP 連接開始,cwnd 設置爲一個報文段,一次只能發送一個;當收到這一個確認的時候,cwnd 加一,於是一次能夠發送兩個;當這兩個的確認到來的時候,每個確認 cwnd 加一,兩個確認 cwnd 加二,於是一次能夠發送四個;當這四個的確認到來的時候,每個確認 cwnd 加一,四個確認 cwnd 加四,於是一次能夠發送八個。可以看出這是指數性的增長。

有一個值 ssthresh 爲 65535 個字節,當超過這個值的時候,要慢下來。

每收到一個確認後,cwnd 增加 1/cwnd,接着上面的過程來,一次發送八個,當八個確認到來的時候,每個確認增加 1/8,八個確認一共 cwnd 增加 1,於是一次能夠發送九個,變成了線性增長。

擁塞的一種表現形式是丟包,需要超時重傳,這個時候,將 sshresh 設爲 cwnd/2,將 cwnd 設爲 1,重新開始慢啓動。但是這種方式會造成網絡卡頓。

快速重傳算法。 當接收端發現丟了一箇中間包的時候,發送三次前一個包的 ACK,於是發送端就會快速的重傳,不必等待超時再重傳。TCP 認爲這種情況不嚴重,因爲大部分沒丟,只丟了一小部分,cwnd 減半爲 cwnd/2,然後 sshthresh = cwnd,當三個包返回的時候,cwnd = sshthresh + 3,是還在比較高的值,呈線性增長。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章