一、傳輸層基本介紹
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報文首部各字段的詳細含義。