【知識詳解】傳輸層詳解
傳輸層詳解
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 詳解