1. 程式人生 > 其它 >【知識詳解】傳輸層詳解

【知識詳解】傳輸層詳解

傳輸層詳解

1.傳輸層概述

1.1 概述

TCP隸屬於傳輸層,所以要首先明白傳輸層的作用是什麼,傳輸層能夠實現端到端的連線。比如說我們用QQ與別人發信息,網路層能夠將資訊傳送到對方的主機上,主機上使用什麼協議來接受這個資訊就由傳輸層來完成,所以傳輸層實現的是程序到程序間的連線。

傳輸層提供的是應用程式間的邏輯通訊,也就是說它向高層(應用層)遮蔽了下面網路層的細節,使應用程式看起來好像是在傳輸層之間沿著水平方向傳輸資料,但事實上兩者之間並沒有這樣一條實際的物理連線。

1.2 功能

  • 1.網路層提供了點到點的連線,而傳輸層提供了端到端的服務,也就是程序間的通訊;
  • 2.網路層提供的是不可靠的連線,傳輸層能夠實現可靠的傳輸;

1.3 協議

  • TCP(Transmission Control:Protocol) 傳輸控制協議
  • UDP(User Datagram Protocol) 使用者資料報協議

1.4 傳輸層和應用層的關係

TCP/UDP加上特定的埠號就可以表示應用層的某個協議;

  • TCP+25: SMTP協議;
  • TCP/UDP+53: DNS協議;
  • TCP+80: Http協議;
  • TCP+443: Https協議;

2.TCP協議

一個TCP連線不僅需要埠,還需要IP地址來確定通訊的主機。所以IP首部中的發
送端IP地址加上傳送端埠號就形成了連線的傳送端;目標端IP地址再加上接收端埠號
就確定了連線的接收端。這樣就唯一地確定了一個TCP連線。

在TCP/IP協議中,TCP協議是基於IP協議的。IP協議是對應於網路層的協議,它是
一個不可靠的協議。TCP協議的可靠性保證給IP協議提供了可靠環境,從而使得IP協議可以不必考慮傳輸的可靠性,專注於網路層的功能。這也是協議分層的初衷。

TCP被認為是一種流式傳輸層服務。它表示TCP傳送端從應用程式接收到字元流,並從這個流中提取適當的長度建立資料段,然後將其傳送到網路上。TCP接收端則接收資料段,從中提取資料,若沒有按序號到達還要對其進行排序,並將其作為字元流交付給接收端應用程式。這樣就完成了資料的傳輸。

下圖是一張典型的TCP面向流的傳輸

問:TCP怎樣實現可靠傳輸?

TCP採用了很多手段來保證可靠傳輸

  • 1.連線管理機制:在傳輸資料前需要進行建立連線,也就是三次握手,在資料傳送完後還需要釋放連線,也就是四次揮手。
  • 2.資料分段:TCP以報文段為單位進行傳送,在建立TCP連線的時候,兩端協商TCP報文段中的資料欄位(也稱為資料包)的最大長度(MSS);其長度加上首部長度就是整個TCP報文段的長度;
  • 3.校驗和:提供了一種簡單的校驗,如果收到段的校驗和和原來的有差別,那接收方就會丟掉這個報文段;
  • 4.序列號:TCP給傳送的資料包的編號,如果接收端收到亂序後會進行重新排序,收到重複的也會進行丟棄;
  • 5.確認應答:接收方收到報文後會回覆確認(累計確認:對所有收到的按序的只確認最後,確認號之前的資料已經全部收到了);
  • 6.重發控制:TCP發出一個報文段後,就會啟動一個定時器,等接收方確認這個報文段,如果不能及時收到確認,將重發這個報文段;
  • 7.流量控制:通訊的雙方都有固定大小的緩衝區,TCP的接收端只允許傳送端傳送接收端緩衝區能接納的資料。當接收方來不及處理髮送方的資料,就把視窗縮小,並把視窗值告訴傳送端(提示傳送方降低傳送的速率,防止包丟失)是利用滑動視窗來實現;
  • 8.擁塞控制:當網路產生擁堵時,減少資料的傳送;主要是通過擁塞視窗來實現;(慢開始和擁塞避免;快重傳和快恢復);

2.1 TCP首部

TCP首部預設有20個位元組的固定首部。從下圖也能看到,4*5=20;以下是首各內容的含義

  • 源埠和目的埠:各佔兩個位元組;(16bit的埠號+32bit的ip地址形成了一個套接字socket,每一條TCP連線唯一的被兩端的兩個端點也就是兩個套接字確認,所以這也構成了傳輸層的點到點通訊)
  • 序號(seq):佔4個位元組;(在傳輸的資料中,每一個位元組都有一個序號,這個序號就是本次傳輸資料的第一個位元組的序號);
  • 確認號(ack):佔4個位元組;(這個值是代表期待收到對方下次傳送的資料的第一個位元組的序號,比如如果傳送ack=301,則表示前300個我收到了,下次你給我發第301個);
  • 資料偏移:佔4位,也叫首部長度(Header length),一般情況下首部長度是20位元組,但是也可以擴充套件,比如這4位都置為1時十進位制是15,代表可以首部可以有15行,一行4個位元組,所以是60個位元組;
  • 6個控制位
URG:緊急指標有效位,和第5行的緊急指標一起用,可以讓緊急資料進行加塞,接收端可以優先快速的獲取緊急資料;
ACK:指示ack確認號是否有效;
PSH:置為1時表示將本報文段立即向上交付有應用層,而不用等快取填滿再交付;
RST:置為1時通知重新建立TCP連線;
SYN:同步序號位,置為1表示需要建立連線;比如SYN=1,ACK=0時表明是一個連線建立請求;而SYN=1,ACK=1,表明是一個連線接受請求;  
FIN:置為1時表明傳送資料結束,連線釋放;
  • 視窗:佔2個位元組:用來說明本地可以接收的資料段的數目,以位元組為單位,流量控制就是基於這個視窗來實現的,其大小是可變的;
  • 檢驗和:佔2個位元組:用來做差錯控制,在傳送端計算一次所有資料的檢驗和,在接收端再計算一次,一致則說明資料基本正確;
  • 緊急視窗:和URG配合使用;

2.2 連線管理機制

三次握手

  • 第一次握手:SYN=1,seq=x,進入SYN-SENT狀態,等待確認;
  • 第二次握手:SYN=1, ACK=1, seq=y, ack=x+1(確認對方的,傳送自己),進入SYN-RECV狀態;
  • 第三次握手:ACK=1, seq=x+1, ack=y+1(確認對方,傳送自己),客戶端伺服器進入ESTABLISHED狀態;
問:為什麼是三次握手?

本質上是為了在不可靠的通道建立可靠的連線,防止已經失效的報文突然又到了伺服器,假設客戶端傳送了一個請求連線,但是因為通道的原因發生了滯留,等了一會沒有收到確認,再次傳送請求連線,這次通道情況較好,很快進行了確認接受了連線,但是過了一會那個滯留的連線到達伺服器,其實已經是一個失效的報文了,伺服器以為客戶端再次發起新的連線,回覆確認。如果採用兩次握手,伺服器發出確認後就建立了連線,但是客戶端並沒有發出連線的請求,所以不會理睬伺服器的確認,那這樣伺服器認為連線已經建立,一直等待客戶端傳送資料,造成資源的浪費。如果是三次握手的話,伺服器會等著客戶端的確認,如果收不到確認,就知道客戶端並沒有想建立連線。

四次揮手

  • 1.客戶端發出連線釋放報文,停止傳送資料,FIN=1,seq=u(等於前面傳過來的最後一個序列號+1,TCP規定FIN報文段即使不攜帶資料,也消耗一個序號),此時客戶端進入FIN-WAIT-1(終止等待1)狀態。
  • 2.伺服器收到連線釋放報文,發出報文確認,ACK=1,ack=u+1,並且帶上自己的序列號,seq=v,此時伺服器進入CLOSE-WAIT狀態,這時候客戶端不發了,但是服務端還要發,客戶端依然要接收。客戶端收到確認請求後,進入FIN-WAIT-2(終止等待2)狀態,等待伺服器傳送連線釋放報文。
  • 3.伺服器傳送完畢後,向客戶端傳送連線釋放報文,FIN=1,ACK=1,ack=u+1,seq=w,此時,伺服器進入LAST-WAIT(最後確認)狀態,等待客戶端確認。
  • 4.客戶端收到連線釋放報文,發出報文確認,ACK=1,ack=w+1,自己的序列號仍是seq=u+1,此時,客戶端進入TIME-WAIT(時間等待)狀態,注意此時TCP連線沒有釋放,必須等待2MSL(最長報文段壽命)時間後,才會進入CLOSE(關閉)狀態。伺服器只要收到了確認後,立馬進入CLOSED狀態。所以伺服器結束時間要比客戶端早一些。
問:為什麼握手是三次而揮手是四次?

因為伺服器收到客戶端的SYN連線建立報文後,可以直接傳送SYN+ACK報文,即應答和同步,但是在關閉連線時,伺服器可能還有資料要傳送,所以只回復一個應答告訴客戶端自己收到了,但是我這不能關,得等我發完了,我才能傳送FIN連線釋放報文。

問:為什麼TIME-WAIT需要2MSL才能返回CLOSE狀態?

因為通道是不可靠的,最後一個ACK確認報文傳送後可能會丟失,伺服器如果沒有收到ACK確認,就會重發FIN連線釋放報文,如果客戶端又收到了,那就知道剛才那個確認丟失了,重發ACK確認。所以,當客戶端在2MSL時間內沒有再次收到FIN報文後,客戶端就知道伺服器已經成功收到了,進入CLOSED狀態。

2.3 確認應答機制(ACK機制)

TCP將每個位元組都進行了編號,也就是序列號

每一個ACK都帶有對應的確認序列號, 意思是告訴傳送者, 我已經收到了哪些資料; 下一次你要從哪裡開始發.

比如, 客戶端向伺服器傳送了1005位元組的資料, 伺服器返回給客戶端的確認序號是1003, 那麼說明伺服器只收到了1-1002的資料.
1003, 1004, 1005都沒收到.
此時客戶端就會從1003開始重發.

2.4 流量控制機制

流量控制:流量控制就是讓傳送方的傳送速率不要太快,要讓接收方來得及處理。TCP連線的每一方都有固定大小的緩衝空間,TCP的接收端只允許傳送端傳送接收端緩衝區能接納的資料。當接收方來不及處理髮送方的資料,就把視窗縮小,並把視窗window值告訴傳送端(提示傳送方降低傳送的速率,防止包丟失)。

TCP使用的流量控制協議是可變大小的滑動視窗協議。(TCP 利用滑動視窗實現流量控制,隨ACK報文傳送),所以首先來看一下滑動視窗

滑動視窗

剛才說了確認應答機制,但是想一下,如果每傳送一個數據段都要傳送一個ACK確認應答後才能傳送下一個資料段,那這樣效能就會很低,吞吐量也很低。所以引入了視窗。

視窗:視窗大小就是指無需等待確認就可以繼續傳送資料的最大值。

  • A的傳送視窗和B的接受視窗都是20個位元組。
  • 只要是在視窗之內的,那A就可以不用等著確認就可以傳送,比如即使紅色部分都沒有收到確認,但是後面的42也都可以傳送,解決吞吐量的問題。
  • 當B給了A一個確認後,比如過了一會給了確認號34,那就表明34之前的都已經收到了,那A的傳送視窗就可以向前滑動了,滑到34位置,然後後面的新到了窗口裡的位元組(51-53)就可以接著傳送。
  • 凡是在傳送窗口裡的都可以直接傳送,移出視窗外的就是已經完全被接收端接收好了的。
  • 如果這時候發生了丟包怎麼處理呢,兩種情況:
    • 1.資料包收到了,但是確認應答丟了,比如B傳送了確認34,但是丟了,然後B又傳送確認45,這時候沒丟,那其實丟失了一部分ACK並沒有太大關係,因為能夠通過後面沒丟的ACK來確認已經收到了哪些資料包。
    • 2.資料包丟了,比如A傳送了31-33,接著發34-41,接著發42-46,但是34-41這個資料段丟了,B沒收到,那就傳送ack=34,而且會連續發3次,為什麼要3次呢,因為如果只發一次不一定丟了,B的確認比A慢一點。你看上面的例子A都發完50了,B可能才確認到34。發3次後,就像是在提醒A:我要的是34。然後傳送端就會把34-41重傳,注意後面的42-46不會重發(選擇確認SACK);

流量控制

接收端根據自己的視窗大小,來告訴傳送方的傳送速率。

  • 接收端通過將自己的視窗大小放入首部中的“視窗大小”欄位,然後通過ack報文通知客戶端。
  • 傳送端根據這個大小來調整自己的傳送速度。如果接收區滿了,那就將視窗設定為0,這時傳送端不再發送,然後定期通過一個視窗探測來試探接收端的視窗大小。

2.5 擁塞控制機制

有了滑動視窗後,TCP就可以高效的傳送大量資料了,但是想一下,如果我們上來就傳送大量資料,網路上的其他計算機、網路狀況都不清楚,就有可能會堵塞。所以TCP引入了擁塞控制機制。

擁塞控制:就是當網路產生擁塞時,減少資料的傳送。
擁塞產生的條件:對資源需求的總和 > 可用資源

擁塞控制歸根結底就是TCP協議想盡可能的把資料傳輸給對方,但是又要避免網路壓力太大出現擁堵的折中方案。

問:流量控制和擁塞控制有什麼區別?

流量控制是端到端的控制,是通訊雙方的一種控制,就是要抑制傳送方的速度使接收方能夠來得及接收和處理,採用滑動視窗來實現。
擁塞控制是解決網路的擁堵問題,它涉及到的不僅是通訊的雙方,而是涉及到網路上所有的主機、路由器,所以這是一個全域性性的過程。

擁塞視窗:TCP中維持一個叫做擁塞視窗(cwnd)的變數。這個視窗根據網路狀況動態變化。

  • 只要網路沒有出現擁塞,就把cwnd增大一點,為了能夠把資料更快傳送出去;
  • 只要網路出現擁堵,就把cwnd減少一點,為了減緩網路的壓力;
  • 網路中實際的傳送視窗大小應該是接收視窗和擁塞視窗的較小一個,即傳送視窗 = min[rwnd, cwnd]; 當cwnd較小時,擁塞視窗限制著傳送速度,當rwnd較小時,接收視窗限制著傳送速度;
慢開始和擁塞避免
  • 慢開始:剛開始設定cwnd為1,然後每經過一個傳輸輪次,cwnd就加倍;
  • 慢開始門限:當cwnd < 慢開始門限時,使用慢開始演算法,也就是指數增長;
          當cwnd > 慢開始門限時,改用擁塞避免演算法,也就是加法增大
    (慢開始門限就是圖中的16);
  • 擁塞避免:讓擁塞視窗緩慢增大,不再是加倍了,而是線性規律緩慢增長(就是想讓網路不容易出現擁塞),這也叫做加法增大;
  • 當網路擁堵時(比如圖中的24),執行兩步動作:
    • 慢開始門限設定為出現擁塞的視窗的一半(變為12), 這也叫乘法減小
    • 將cwnd設定為1,重新執行慢開始演算法;

這樣做就是想迅速減少網路的擁堵,讓網路能夠把擁塞的報文先處理了;

快重傳和快恢復

在沒有快重傳時,如果一個數據段丟失了,會等待一定的超時週期才重傳(每傳送一個數據段之後就會啟動一個計時器),這增加了時延;

  • 接收端收到A的1報文後,傳送ACK2,然後2丟失,接收端會連發3個ACK2,這時候傳送端會立即重傳2,而不用管計數器了。
  • 如果打開了SACK(選擇確認),那後面我們正常收到的,比如3會放在緩衝區裡,就不用再次重傳了,包括後面的5-11,都不會再次重傳,只會重傳丟失的資料包,但是如果沒有開啟SACK,就會把2後面的所有資料段都進行重傳;

問:為什麼會選擇3次呢?

首先要明白這個3次指的是3次冗餘,是不包括前面的正常確認的。
原因就是因為網路傳輸是不可靠的,在將不同資料段傳送的時候,可能會導致到達接收端的順序是不一樣的,也就是亂序,比如後面的N+1到了,N+2到了,但是N沒到,那這時候可能等一等一會就到了,也可能就是丟了,在發3次的時候A丟包的可能性是最高的。所以選擇3,其實在實際抓包的時候,快重傳都會在大於3後發生;

  • 當收到3個連續的重複確認後,A其實並不能判斷是否擁塞,丟包了,好像擁塞了,但是B的3次確認又都能收到,又好像沒堵。
  • 快恢復和前面的區別就在於當執行快重傳演算法後,同樣將慢開始門限設為當前視窗的一半,但是不再重新慢開始了,而是直接從新的慢開始門限開始執行擁塞避免,也就是加法增大。這樣提高了恢復速度。

3. UDP協議

3.1 UDP首部

UDP首部預設是8個位元組的固定長度。

  • 源埠和目的埠:各佔兩個位元組;(16bit的埠號+32bit的ip地址形成了一個套接字socket,每一條TCP連線唯一的被兩端的兩個端點也就是兩個套接字確認,所以這也構成了傳輸層的點到點通訊)
  • 長度:佔2個位元組,是UDP資料報的長度(包括首部和資料),最小為8,只有首部;
  • 校驗和:佔2個位元組,是可選的,提供簡單的校驗。這是UDP提供的唯一可靠機制。

3.2 UDP的特點

有時候TCP顯得不太合適,比如說要傳送一個4個位元組的資料,如果使用TCP,就要給其加上至少20位元組的頭部資訊,而且還要確認,時間大大降低。所以在傳輸效率高的時候用UDP,其只需要8個位元組的首部,而且不需要確認。

UDP是面向報文的,應用層交下來的報文,不合並也不拆分,新增UDP首部後就直接向下交付給IP層,也就是一次傳送一個報文;

UDP在傳送資料之前不需要建立連線,收到後也不需要給出確認,所以沒有辦法保證可靠交付。

4. TCP和UDP的區別

兩者類似於打電話和寫信的區別,兩個人打電話時,雙方需要確認並建立連線才能通訊。 在郵局寄信時,只需要將信放信箱就行了,不用告訴對方。

問:TCP和UDP的特點和區別?

  • 1.兩者所有的區別都是因為兩者的目的是不同的,TCP目的是提供可靠的資料傳輸,所以其採用了很多措施來達到這一目的,比如連線管理,確認機制,流量控制,擁塞控制等等,但是UDP並不一定提供可靠的交付,它提供的最大努力的交付,並不一定保證傳輸過去後是準確無誤的,它是想盡可能快的傳送儘可能多的資訊(比如說像即時通訊);
  • 2.正是因為上面說的兩者的目的不同,所以有了很多具體的區別。
    • 比如TCP是面向連線的,在傳輸資料之前需要先建立連線,資料傳送完畢後也需要關閉連線,而UDP不需要連線。
    • 比如TCP是面向位元組流的,而UDP是面向報文的。
    • 比如TCP需要有確認應答機制,而UDP不需要。

問:TCP的面向位元組流和UDP的面向報文怎麼理解?

  • TCP是面向位元組流的協議,也就是說資料是以位元組流的形式傳遞給對方的,沒有固定的報文或者說報文邊界概念。雙方都會有一個緩衝區,如果位元組流太長,TCP就會拆分進行傳送,如果位元組流很短,那也可以等著緩衝區中的位元組流變長了以後再構成一個報文段進行傳送。
  • UDP是面向報文的協議,應用層交給UDP多長的協議,就傳送多長的報文,不合並也不拆分,保留報文的邊界,一次傳送一個。

參考連結

TCP/IP第四層--傳輸層TCP和TPC資料報文詳解

TCP 詳解