一、傳輸層基本介紹
1. 基本職能
傳輸層位於計算機網路體系五層結構中的第四層,它的職能是:為執行在不同主機上的程式提供直接的通訊服務。
和網路層提供服務的範圍差異如下圖所示:

即網路層提供了主機到主機間的通訊(如果是IP協議的話還是不可靠的通訊),而傳輸層提供的是主機中的程式與程式之間的通訊(TCP協議提供可靠傳輸,UDP協議提供不可靠傳輸)。
更加直觀的示意圖如下所示:

2. 運輸層埠號、複用分用的概念
埠號
為了使執行不同作業系統的計算機的應用程式之間能夠進行網路通訊,就必須使用統一的方法對TCP/IP體系的應用程式進行標識。
這裡用於標識不同應用程式的東西就是埠號:
- 埠號使用16位元表示,取值範圍0~65535;
- 埠號只具有本地意義,即埠號只是為了標識本計算機應用層中的各程式,在因特網中,不同計算機中的相同埠號是沒有聯絡的。
埠號分類:
熟知埠號 | 登記埠號 | 短暫埠號 |
---|---|---|
熟知埠號: 0~1023, IANA把這些埠號指派給了TCP/IP體系中最重要的一些應用協議,例如: FTP使用21/20,HTTP使用80,DNS使用53。 | 1024~49151, 為沒有熟知埠號的應用程式使用。使用這類埠號必須在IANA按照規定的手續登記,以防止重複。例如:Microsoft RDP微軟遠端桌面使用的埠是3389。 | 49152~65535, 留給客戶程式選擇暫時使用。當伺服器程式收到客戶程式的報文時,就知道了客戶程式所使用的動態埠號。通訊結束後,這個埠號可供其他客戶程式以後使用。 |
傳送方的複用和接收方的分用

TCP/IP體系結構應用層常用協議所使用的運輸層熟知埠號:

二、UDP與TCP對比
UDP和TCP是計算機網路層的兩個重要協議,如下圖所示:

1. 是否連線
UDP協議是無連線的,TCP協議是面向連線的,如下所示:

2. 單播、多播和廣播
UDP | TCP |
---|---|
![]() |
![]() |
3. 面向報文和麵向位元組流

之所以TCP需要面向位元組流,是因為TCP需要實現可靠傳輸、流量控制和擁塞控制,面向位元組流是實現上述技術的基礎。
4. 可靠性

5. 兩種協議的格式
UDP | TCP |
---|---|
![]() |
![]() |
因為TCP需要實現的功能較為複雜,因此TCP報文段的首部要比UDP資料包的首部大得多。
6. 小結

三、TCP的流量控制
一般情況下,我們都是希望資訊可以儘快傳輸,但如果是TCP連線一對一進行傳輸時,如果不進行流量控制,就會出現一方傳輸速度過快,導致另一方的接收資訊的快取滿了,如果再繼續傳送資訊只會導致這部分資訊的丟失,然後需要進行資訊重傳等操作,進而不僅資訊傳輸比原來要慢很多,還佔用了很多額外的網路資源。
TCP協議採用了滑動視窗的機制來進行流量控制。
1. 流量控制的相關術語
傳送視窗和接收視窗
邏輯上,傳送端有一個控制傳送資料量的視窗,稱為傳送視窗,當傳送端將傳送視窗中的所有資料都傳送出去後,還沒有收到接收端的應答之前,都不能進行下一步的操作,例如移動視窗,傳送新資料等等。
而接收視窗相當於接收端當前可以接受資料量的大小。
傳送視窗的大小由接收端(接收視窗大小)來決定,這是保證流量控制,保證資料不溢位的關鍵。
2. 流量控制的流程
- 傳送端傳送自己傳送視窗中的全部或部分資料到接收端,例如(淺藍色部分為已傳送部分):
- 接收端接收到後傳送相應資料,其中包括:對資料的累計確認和當前接收視窗的大小(rwnd)。
- 傳送端接收到資料確認資訊和rwnd後將①傳送視窗前移,②調整視窗的大小,再將已確認的資料從傳送快取中刪除,然後回到1繼續進行


當前接收方傳送的rwnd為0,即接受視窗的大小為0,所以傳送視窗也被調控為0,因而傳送方無法繼續傳送資料。
考慮當接收方又出現了一定的接收空間,然後將當前的rwnd傳送到傳送方,但此時這個報文段丟失了,那麼傳送端無法接收到rwnd的變化資訊,因而又無法傳送資料,此時就會造成雙方都在等待對方相應的狀況,即死鎖,如下圖所示:

其實這種情況下,即傳送方接收到rwnd=0
的資訊後會啟動持續計時器,當這個階段還未接收到接收端發來的資訊時就會傳送零視窗探測報文進行詢問,以打破死鎖局面:

疑問1:零視窗探測報文如果丟失了怎麼處理?回答:零視窗探測報文也有超時重傳計時器,保證可以不斷髮送探測報文
疑問2:如果接收視窗為0如何接收零視窗探測報文?回答:TCP規定這種特殊情況的報文接收端也必須有機制進行接收
例題:

3. 小結

四、TCP的擁塞控制
1. 簡單介紹

2. 擁塞控制演算法
包括四個子演算法:
- 慢開始
- 擁塞避免
- 快重傳
- 快恢復
3. 相關概念
為了實現擁塞控制,傳送方除了需要維護swnd(傳送視窗)之外,還需要額外維護一個新的變數cwnd(擁塞視窗),它的值取決於擁塞程度,而且動態變化。
此時,swnd = min(rwnd, cwnd)
,即傳送視窗的大小應為接收視窗和擁塞視窗的最小值,進而同時實現流量控制和擁塞控制。
cwnd的變化規律:
- 網路沒有出現擁塞時,cwnd再增大一些
- 一旦出現擁塞,cwnd就要減小一些
判斷網路是否發生擁塞的依據:
- 重傳定時器超時
- 收到三個相同(重複)的 ACK
其實這兩個依據的本質都是相同的,即發出的報文段丟失了。
最後,為了cwnd的增大變化更加合理,在特定的情況下采用特定的演算法進行增大,傳送端還需要維護一個慢開始門限變數ssthresh狀態變數:

4. 擁塞控制的流程
為了能夠更簡單地說明問題,假定如下條件:

4.1 慢開始
連線成功後,假設傳送端的擁塞視窗值被設定為1,此外還需要設定慢開始門限的初始值,這裡以16為例。
慢開始演算法:每次收到一個ACK,cwnd += 1。
具體案例如下所示:

因此在理想情況下執行慢開始演算法時是每接收到一輪迴復時cwnd *= 2
,我們在做題時往往是考慮這樣的理想情況的。
擁塞視窗的大小隨傳輸輪次的增大的變化如下圖所示:

4.2 擁塞避免
當cwnd達到ssthresh(慢開始門限)時,就會轉而執行擁塞避免演算法,即:每收到一個新的ACK,將CWND += MSS / CWND
在理想條件下,若每個ACK都沒有延遲,則在每個RTT之後,cwnd的變化相當於cwnd += 1
。

當出現某報文段發生超時重傳時,判斷網路發生了擁塞,此時進行如下操作:


即步驟為:
- 執行慢開始演算法
- cwnd達到ssthresh後執行擁塞避免演算法
- 發生擁塞後更新:
ssthresh /= 2; cwnd = 1;
,然後轉1繼續執行
按照以上步驟執行直到資訊傳送完全為止。
因而總的流程如下圖所示:

tips:
- “慢開始”是指一開始向網路注入的報文段少,並不是指擁塞視窗cwnd增長速度慢;
- “擁塞避免”並非指完全能夠避免擁塞,而是指在擁塞避免階段將擁塞視窗控制為按線性規律增長,使網路比較不容易出現擁塞;
慢開始和擁塞避免演算法是1988年提出的TCP擁塞控制演算法(TCP Tahoe版本)。
1990年又增加了兩個新的擁塞控制演算法(改進TCP的效能),這就是快重傳和快恢復(TCP Reno版本)。
原因:有時,個別報文段會在網路中丟失,但實際上網路並未發生擁塞。這將導致傳送方超時重傳,並誤認為網路發生了擁塞,進而傳送方把擁塞視窗cwnd又設定為最小值1,並錯誤地啟動慢開始演算法,因而降低了傳輸效率。
4.3 快重傳

執行快重傳演算法的過程如下:

即使用這個演算法可以減少傳送端對網路擁塞的誤判,使傳送端更早地對丟失報文段進行重傳,進而提高傳輸效率。
4.4 快恢復

4.5 四種演算法的綜合使用
下圖的傳輸過程包括了四種演算法的使用:

TCP Reno版本的擁塞控制如下:

5. 例題

五、TCP超時重傳時間RTO的計算
1. 問題引入
-
RTO太小時
-
RTO太大時
可見,RTO太小或太大都不合適,太小時會使網路符合增大,太大時會降低傳輸速率。
因此,一般我們會取一個比往返時間RTT稍大的值作為RTO的值,如下圖所示:

2. RTO計算公式
要計算RTO,首先我們需要先計算加權平均往返時間RTTS,計算公式為:

即新的RTTS由新的RTT樣本和舊的RTTS同時決定,裡面α的取值確定了兩者的重要性,根據標準一般取值為1/8,即舊的RTTS權重較大:

而RTO的大小要略大於RTTS,其完整的計算公式如下:

RTTS的計算過程已經提到過了,即:

而RTTD的計算如下:

按道理我們已經可以計算每一傳輸輪次的RTTS了,但是實際上還是會出現問題,這裡主要是RTT樣本在發生重傳時很可能出現偏差,如下圖所示:

因此我們需要解決這種網路不可靠情況下的RTT測量問題,這裡主要是使用Karn演算法:
在計算RTTS的過程中,只要報文段進行了重傳,就不採用該報文傳輸得到的RTT樣本。(樣本重傳不採用)
但這樣也會出現特殊情況無法更新RTO:報文段的時延突然增大了很多,並且之後很長一段時間都會保持這種時延。因此在原來得出的重傳時間內,不會收到確認報文段。於是就重傳報文段。但根據Karn演算法,不考慮重傳的報文段的往返時間樣本。這樣,超時重傳時間就無法更新。這會導致報文段反覆被重傳。
因此我們使用修正後的Karn演算法:報文段每重傳一次,就把超時重傳時間RTO增大一些。典型的做法是將新RTO的值取為舊RTO值的2倍。(RTO *= 2
)
以下是一個計算的例子:

總的計算方法如下圖所示:

六、TCP滑動視窗和可靠傳輸
1. 基於滑動視窗的傳送過程
TCP基於以位元組為單位的滑動視窗來實現可靠傳輸。
滑動視窗示意圖如下所示:

實現上維護3個指標來描述傳送視窗的狀態:

具體的報文段傳送過程如下所示:

2. 注意點
傳送視窗大小

對不按序到達資料的處理

確認機制

通訊方式

3. 例題
例1:

例2:

七、TCP連線的建立
TCP是面向連線的協議,它基於運輸連線來傳送TCP報文段。因此TCP運輸連線的建立和釋放是每一次面向連線的通訊中必不可少的過程。

1. 連線建立需要解決的問題

2. 連線的建立過程
首先TCP伺服器自身先建立相應的傳輸控制塊,內容如下,並進入監聽狀態,等待TCP客戶程式的連線請求:

然後TCP客戶端傳送TCP連線請求 SYN = 1, seq = x
,SYN設定為1代表這是一個連線請求,且TCP規定當SYN設定為1的報文段不能攜帶資料,並要消耗掉一個序號seq,示意圖如下:

當TCP伺服器接收到該請求後,會傳送一個TCP連線請求的確認,SYN = 1, ACK = 1
代表這是對連線請求的確認,而 ack = x+1
表示對收到的請求報文的應答。同理,這個報文段也不能攜帶資料並要消耗掉一個序號seq。

最後TCP客戶端接收到伺服器的確認後還需再傳送一個報文段進行應答,至TCP伺服器接收到該報文後,連線正式建立:

三報文握手能否簡化成兩報文?
不能,一個簡單的考量是:
- TCP客戶傳送連線請求後TCP伺服器接收到時可以證明TCP客戶端可以傳送資料
- TCP伺服器傳送連線確認報文TCP客戶接收到後可以證明伺服器可以傳送和接收資料
但如果不再傳送一個額外的請求則無法證明客戶端可以接受資料,因而無法保證連線的可靠性。
另外特殊的情況如下圖所示:
![]()
3. 例題

八、TCP連線的釋放
TCP通過“四報文揮手”釋放連線。客戶端和伺服器都可以發起釋放連線請求。
這裡假設TCP客戶端主動發起釋放連線請求:

其中 FIN = 1
表示這是釋放連線請求報文段,另外ACK = 1, ack = v
為對前面接收到的報文段進行確認,同理,釋放連線請求也需要消耗掉一個序號seq = u
。
然後TCP伺服器傳送一個釋放連線的確認報文,並通知應用程式,至此TCP客戶到伺服器的單向傳輸就關閉了:

此時TCP連線處於半關閉狀態,即客戶到伺服器的連線斷開,但伺服器到客戶的連線仍繼續,伺服器還可以繼續向客戶端傳送資料:

當伺服器要傳送的資料也傳送結束後,則伺服器端也會傳送一個釋放伺服器到客戶端方向連線的請求,和客戶端傳送的釋放請求的過程基本一致:

而客戶端接收到釋放請求時傳送釋放確認,並在等待2MSL後關閉連線,而伺服器接收到該確認後直接關閉連線:

最後的這個等待時間是為了防止發生這種情況:

此外當連線過程中客戶端出現故障時有這樣的處理方案:

九、TCP報文的首部格式
1. 位元組流和TCP報文段的關係

2. 格式與各部分的功能
整體格式如下圖所示:

- 源埠:佔16位元,寫入源埠號,用來標識傳送該TCP報文段的應用程式。
- 目的埠:佔16位元,寫入目的埠號,用來標識接收該TCP報文段的應用程式。

- 序號seq:佔32位元,取值範圍[0, 232- 1],序號增加到最後一個後,下一個序號就又回到0。
指出本TCP報文段資料載荷的第一個位元組的序號。

-
確認號ack:佔32位元,取值範圍[0, 232- 1],確認號增加到最後一個後,下一個確認號就又回到0。
指出期望收到對方下一個TCP報文段的資料載荷的第一個位元組的序號,同時也是對之前收到的所有資料的確認。(累計確認)
若確認號=n,則表明到序號n-1為止的所有資料都已正確接收,期望接收序號為n的資料。 -
確認標誌位ACK:取值為1時確認號欄位才有效;取值為0時確認號欄位無效。
TCP規定,在連線建立後所有傳送的TCP報文段都必須把ACK置1。

- 資料偏移:佔4位元, 並以4位元組為單位。
用來指出TCP報文段的資料載荷部分的起始處距離TCP報文段的起始處有多遠。
這個欄位實際上是指出了TCP報文段的首部長度。
首部固定長度為20位元組,因此資料偏移欄位的最小值為(0101)2
首部最大長度為60位元組,因此資料偏移欄位的最大值為(1111)2

-
保留:佔6位元,保留為今後使用,但目前應置為0。
-
視窗:佔16位元,以位元組為單位。指出傳送本報文段的一方的接收視窗(cwnd)。
視窗值作為接收方讓傳送方設定其傳送視窗的依據。
這是以接收方的接收能力來控制傳送方的傳送能力,稱為流量控制。 -
校驗和:佔16位元,檢查範圍包括TCP報文段的首部和資料載荷兩部分。
在計算校驗和時,要在TCP報文段的前面加上12位元組的偽首部。
幾個標誌位:
-
同步標誌位SYN:在TCP連線建立時用來同步序號。
-
終止標誌位FIN:用來釋放TCP連線。
-
復位標誌位RST:用來復位TCP連線。
當RST=1時,表明TCP連線出現了異常,必須釋放連線,然後再重新建立連線。
RST置1還用來拒絕一個非法的報文段或拒絕開啟一個TCP連線。 -
推送標誌位PSH:接收方的TCP收到該標誌位為1的報文段會儘快上交應用程式,而不必等到接收快取都填滿後再向上交付。
URG和緊急指標:
緊急標誌位URG:取值為1時緊急指標欄位有效;取值為0時緊急指標欄位無效。
緊急指標:佔16位元,以位元組為單位,用來指明緊急資料的長度。
當傳送方有緊急資料時,可將緊急資料插隊到傳送快取的最前面,並立刻封裝到一個TCP報文段中進行傳送。緊急指標會指出本報文段資料載荷部分包含了多長的緊急資料,緊急資料之後是普通資料。
選項部分:

- 填充:由於選項的長度可變,因此使用填充來確保報文段首部能被4整除
(因為資料偏移欄位,也就是首部長度欄位,是以4位元組為單位的)。
以上就是TCP報文首部各欄位的詳細含義。