1 傳輸層概述
1.1 傳輸層的功能
- 端到端通信:提供應(yīng)用進(jìn)程間的端到端通信(邏輯通信)。因此傳輸層又稱為端到端協(xié)議。
- 差錯(cuò)檢測(cè):對(duì)首部和數(shù)據(jù)部分進(jìn)行檢測(cè)。
- 兩種協(xié)議:面向連接的 TCP、無連接的 UDP。
- 復(fù)用和分用:
概念 | 解釋 |
---|---|
傳輸層 TCP 復(fù)用 | 發(fā)送方的部分應(yīng)用進(jìn)程的報(bào)文在傳輸層使用 TCP 協(xié)議進(jìn)行封裝 |
傳輸層 UDP 復(fù)用 | 發(fā)送方的部分應(yīng)用進(jìn)程的報(bào)文在傳輸層使用 UDP 協(xié)議進(jìn)行封裝 |
網(wǎng)際層 IP 復(fù)用 | 發(fā)送方不同協(xié)議的數(shù)據(jù)都可以封裝成 IP 數(shù)據(jù)報(bào)(IP 協(xié)議字段,TCP 為 6,UDP 為 17) |
網(wǎng)際層 IP 分用 | 接收方的網(wǎng)際層在去除首部后把數(shù)據(jù)交付給上層相應(yīng)的協(xié)議(TCP 或 UDP) |
傳輸層 TCP 分用 | 接收方的傳輸層使用 TCP 協(xié)議去除首部后把數(shù)據(jù)交付給目的應(yīng)用進(jìn)程 |
傳輸層 UDP 分用 | 接收方的傳輸層使用 UDP 協(xié)議去除首部后把數(shù)據(jù)交付給目的應(yīng)用進(jìn)程 |
1.2 端口號(hào)
- 端口:應(yīng)用進(jìn)程通過端口號(hào)進(jìn)行標(biāo)識(shí)。端口號(hào)長度為 16b,能表示 65535 個(gè)不同的端口號(hào)。
端口號(hào) | 類型 | 解釋 |
---|---|---|
0 ~ 1023 | 熟知端口號(hào)(服務(wù)端用) | 由 IANA 分配給 TCP/IP 體系結(jié)構(gòu)應(yīng)用層中最重要的一些應(yīng)用協(xié)議 |
1024 ~ 49151 | 登記端口號(hào)(服務(wù)端用) | 為沒有熟知端口號(hào)的應(yīng)用程序使用。要使用這類端口號(hào),必須在 IANA 進(jìn)行登記,以防止重復(fù) |
49152 ~ 65535 | 短暫端口號(hào)(客戶端用) | 僅在客戶端使用,由客戶進(jìn)程在運(yùn)行時(shí)動(dòng)態(tài)選擇,通信結(jié)束后會(huì)被系統(tǒng)收回,以便給其他客戶進(jìn)程使用 |
- 需記憶的熟知端口號(hào):
FTP | SMTP | DNS | DHCP | HTTP | BGP | HTTPS | RIP |
---|---|---|---|---|---|---|---|
21/20 | 25 | 53 | 67/68 | 80 | 179 | 443 | 520 |
【注】OSPF 不使用傳輸層協(xié)議,所以沒有對(duì)應(yīng)的端口號(hào)。但 OSPF 的 IP 協(xié)議字段值為 89。
2 TCP 報(bào)文段
2.1 TCP 報(bào)文段首部格式
- 源端口和目的端口:各占 2b,端口是傳輸層與應(yīng)用層的服務(wù)接口。
- 序號(hào)(seq):占 32b,取值范圍 0 ~ 232-1。用來指出本 TCP 報(bào)文段的第一個(gè)字節(jié)的序號(hào)。
- 確認(rèn)號(hào)(ack):占 32b,取值范圍 0 ~ 232-1。用來指出期望收到對(duì)方下一個(gè) TCP 報(bào)文段的第一個(gè)字節(jié)的序號(hào),同時(shí)也是對(duì)之前收到的所有數(shù)據(jù)的確認(rèn)。若確認(rèn)號(hào)為 N,則表明序號(hào) N-1 為止的所有數(shù)據(jù)都已收到。
- 數(shù)據(jù)偏移(首部長度):占 4b,表示 TCP 首部長度。該字段的取值以 4B 為單位,最大字段值為 15,因此 TCP 首部最大長度為 60B。
- 保留:占 6b,保留為今后使用,但目前應(yīng)置位 0。
- 緊急位(URG):當(dāng) URG=1 時(shí),此報(bào)文段有緊急數(shù)據(jù),應(yīng)盡快傳送。
- 確認(rèn)位(ACK):當(dāng) ACK=1 時(shí),確認(rèn)號(hào)字段才有效。TCP 連接建立后,ACK 必須為 1。
- 推送位(PSH):當(dāng) PSH=1 時(shí),就盡快地交付給應(yīng)用進(jìn)程,而不再等到接收到足夠多的數(shù)據(jù)才向上交付。
- 復(fù)位位(RST):當(dāng) RST=1 時(shí),表明TCP連接中出現(xiàn)嚴(yán)重差錯(cuò),必須釋放連接,然后再重新建立連接。
- 同步位(SYN):當(dāng) SYN=1 且 ACK=0 時(shí),表明這是一個(gè) TCP 連接請(qǐng)求報(bào)文段。對(duì)方若同意建立連接,則應(yīng)在響應(yīng)的 TCP 報(bào)文段的首部中使 SYN=1 且 ACK=1。
- 終止位(FIN):當(dāng) FIN=1 時(shí),表明此 TCP 報(bào)文段的發(fā)送方已經(jīng)將全部數(shù)據(jù)發(fā)送完畢,現(xiàn)在要求釋放 TCP 連接。
- 窗口:占 16b,指出發(fā)送本報(bào)文段的一方的接收窗口的大小,即接收緩存的可用空間大小,用來表征接收方的接收能力。該字段的取值以 1B 為單位。
- 校驗(yàn)和:占 16b,用來檢查整個(gè) TCP 報(bào)文段在傳輸過程中是否出現(xiàn)了誤碼。
- 緊急指針:占 16b,用來指明緊急數(shù)據(jù)的長度。該字段的取值以 1B 為單位。
- 選項(xiàng):長度可變,有多種選項(xiàng)。其中有個(gè)選項(xiàng)為最大報(bào)文段長度(Maximum Segment Size,MSS),表示報(bào)文段中數(shù)據(jù)部分的最大長度。
- 填充:為了使整個(gè)首部長度是 4B 的整數(shù)倍。
【注】重點(diǎn)關(guān)注 seq、ack、ACK、SYN、FIN 這幾個(gè)位。
2.2 TCP 數(shù)據(jù)傳送的過程
假設(shè)有客戶機(jī) A 和服務(wù)器 B 已經(jīng)建立了 TCP 連接。
(1)現(xiàn) A 向 B 發(fā)送 TCP 確認(rèn)報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=201, ack=800, ACK=1 | 100B(seq=201~300) |
-
seq=201
:指 A 的數(shù)據(jù)部分是從序號(hào) 201 開始的,數(shù)據(jù)部分總長 100B,因此數(shù)據(jù)部分的最后一個(gè)序號(hào)是 300。 -
ack=800
:指 A 期望 B 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 800 開始的。 -
ACK=1
:連接建立后所有傳送的報(bào)文段都必須置 1。
(2)然后 B 向 A 發(fā)送 TCP 確認(rèn)報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=800, ack=301, ACK=1 | 200B(seq=800~999) |
-
seq=800
:指 B 的數(shù)據(jù)部分是從序號(hào) 800 開始的,數(shù)據(jù)部分總長 200B,因此數(shù)據(jù)部分的最后一個(gè)序號(hào)是 999。 -
ack=301
:指 B 期望 A 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 301 開始的,同時(shí)確認(rèn) A 的報(bào)文段(seq=201~300)已收到。 -
ACK=1
:連接建立后所有傳送的報(bào)文段都必須置 1。
(3)若 A 向 B 發(fā)送 3 個(gè) TCP 確認(rèn)報(bào)文段,其中第 2 個(gè)報(bào)文段丟失:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=201, ack=x, ACK=1 | 100B(seq=201~300) |
seq=301, ack=x, ACK=1 | 100B(seq=301~400)(丟失) |
seq=401, ack=x, ACK=1 | 100B(seq=401~500) |
則 B 僅正確接收第 1 個(gè)和第 3 個(gè)報(bào)文段。此時(shí) B 向 A 發(fā)送的 TCP 報(bào)文段,應(yīng)對(duì)已正確接收且按序到達(dá)的最后一個(gè) TCP 報(bào)文段確認(rèn),這就是累積確認(rèn)(更詳細(xì)的解釋見第 4 節(jié)內(nèi)容):
首部 | 數(shù)據(jù)部分 |
---|---|
seq=x, ack=301, ACK=1 | 200B(seq=x~x+199) |
3 TCP 連接管理
TCP 連接有三個(gè)階段:連接建立、數(shù)據(jù)傳送(上面已述)、連接釋放。
3.1 TCP 連接的建立——三次握手
假設(shè)有客戶機(jī) A 和服務(wù)器 B 準(zhǔn)備建立 TCP 連接。
服務(wù)器 B 進(jìn)程處于 LISTEN(監(jiān)聽)狀態(tài),等待客戶機(jī) A 的連接請(qǐng)求。
3.1.1 客戶機(jī)向服務(wù)器發(fā)送 TCP 連接請(qǐng)求報(bào)文段
客戶機(jī) A 向服務(wù)器 B 發(fā)送 TCP 連接請(qǐng)求報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=x, ack=0, SYN=1, ACK=0 | SYN 報(bào)文段不能攜帶數(shù)據(jù) |
-
seq=x
:隨機(jī)選取一個(gè)初始序號(hào) x,作為客戶機(jī) A 的 TCP 報(bào)文段數(shù)據(jù)部分的初始序號(hào)。 -
ack=0
:由于 ACK=0,所以 ack 字段無效。 -
SYN=1
:TCP 連接請(qǐng)求報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 1。 -
ACK=0
:當(dāng) SYN=1,ACK=0 時(shí),表明這是一個(gè) TCP 連接請(qǐng)求報(bào)文段。
此時(shí),客戶機(jī) A 進(jìn)入 SYN-SENT(同步已發(fā)送)狀態(tài)。
【注】TCP 規(guī)定同步標(biāo)志位 SYN 被設(shè)置為 1 的報(bào)文段(例如 TCP 連接請(qǐng)求報(bào)文段和 TCP 連接請(qǐng)求確認(rèn)報(bào)文段)不能攜帶數(shù)據(jù),但要消耗掉一個(gè)序號(hào)。
3.1.2 服務(wù)器向客戶機(jī)發(fā)送 TCP 連接請(qǐng)求確認(rèn)報(bào)文段
服務(wù)器 B 收到 TCP 連接請(qǐng)求報(bào)文段后,向客戶機(jī) A 發(fā)送 TCP 連接請(qǐng)求確認(rèn)報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=y, ack=x+1, SYN=1, ACK=1 | SYN 報(bào)文段不能攜帶數(shù)據(jù) |
-
seq=y
:隨機(jī)選取一個(gè)初始序號(hào) y,作為服務(wù)器 B 的 TCP 報(bào)文段數(shù)據(jù)部分的初始序號(hào)。 -
ack=x+1
:服務(wù)器 B 期望收到客戶機(jī) A 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 x+1 開始的,同時(shí)確認(rèn)客戶機(jī) A 的報(bào)文段(seq=x)已收到。 -
SYN=1
:TCP 連接請(qǐng)求確認(rèn)報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 1。 -
ACK=1
:當(dāng) SYN=1,ACK=1 時(shí),表明這是一個(gè) TCP 連接請(qǐng)求確認(rèn)報(bào)文段。
此時(shí),服務(wù)器 B 進(jìn)入 SYN-RCVD(同步已接收)狀態(tài)。
3.1.3 客戶機(jī)向服務(wù)器發(fā)送 TCP 確認(rèn)報(bào)文段
客戶機(jī) A 收到 TCP 連接請(qǐng)求確認(rèn)報(bào)文段后,向服務(wù)器 B 發(fā)送 TCP 確認(rèn)報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=x+1, ack=y+1, SYN=0, ACK=1 | TCP 確認(rèn)報(bào)文段可以攜帶數(shù)據(jù) |
-
seq=x+1
:客戶機(jī) A 的 TCP 報(bào)文段數(shù)據(jù)部分的序號(hào)為 x+1。 -
ack=y+1
:客戶機(jī) A 期望收到服務(wù)器 B 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 y+1 開始的,同時(shí)確認(rèn)服務(wù)器 B 的報(bào)文段(seq=y)已收到。 -
SYN=0
:TCP 確認(rèn)報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 0。 -
ACK=1
:當(dāng) SYN=0,ACK=1 時(shí),表明這是一個(gè)普通的 TCP 確認(rèn)報(bào)文段。
此時(shí),客戶機(jī) A 進(jìn)入 ESTABLISHED(連接已建立)狀態(tài)。
【注】TCP 規(guī)定普通的 TCP 確認(rèn)報(bào)文段可以攜帶數(shù)據(jù),但如果不攜帶數(shù)據(jù),則不消耗序號(hào)。如果該報(bào)文段不攜帶數(shù)據(jù),則客戶機(jī) A 要發(fā)送的下一個(gè)數(shù)據(jù)報(bào)文段的序號(hào)仍為 x+1。
服務(wù)器 B 收到 TCP 確認(rèn)報(bào)文段后,也進(jìn)入 ESTABLISHED(連接已建立)狀態(tài)。至此 TCP 連接已建立。
【總結(jié)】TCP 建立連接的過程:
客戶機(jī):“我有話要跟你講,不知可不可以?”
服務(wù)器:“可以,你講吧!”
客戶機(jī):“好的!blablabla”
3.2 TCP 連接的釋放——四次揮手
假設(shè)有客戶機(jī) A 和服務(wù)器 B 準(zhǔn)備釋放 TCP 連接。
客戶機(jī) A 進(jìn)程和服務(wù)器 B 進(jìn)程處于 ESTABLISHED(連接已建立)狀態(tài)。
3.2.1 客戶機(jī)向服務(wù)器發(fā)送 TCP 連接釋放報(bào)文段
客戶機(jī) A 向服務(wù)器 B 發(fā)送 TCP 連接釋放報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=u, ack=v, FIN=1, ACK=1 | FIN 報(bào)文段可攜帶也可不攜帶數(shù)據(jù) |
-
seq=u
:客戶機(jī) A 的 TCP 報(bào)文段數(shù)據(jù)部分的序號(hào)為 u,它等于客戶機(jī) A 之前已傳送數(shù)據(jù)部分的最后一個(gè)字節(jié)的序號(hào)加 1。 -
ack=v
:ack 字段的值為 v,它等于客戶機(jī) A 之前已收到數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)加 1。 -
FIN=1
:TCP 連接釋放報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 1。 -
ACK=1
:當(dāng) FIN=1,ACK=1 時(shí),表明這是一個(gè) TCP 連接釋放報(bào)文段。
【注】TCP 規(guī)定,終止標(biāo)志位 FIN 等于 1 的 TCP 報(bào)文段即使不攜帶數(shù)據(jù),也要消耗掉一個(gè)序號(hào)。
此時(shí),客戶機(jī) A 進(jìn)入 FIN-WAIT-1(終止等待 1)狀態(tài)。
3.2.2 服務(wù)器向客戶機(jī)發(fā)送 TCP 確認(rèn)報(bào)文段
服務(wù)器 B 收到 TCP 連接釋放報(bào)文段后,向客戶機(jī) A 發(fā)送 TCP 確認(rèn)報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=v, ack=u+1, FIN=0, ACK=1 | TCP 確認(rèn)報(bào)文段可以攜帶數(shù)據(jù) |
-
seq=v
:服務(wù)器 B 的 TCP 報(bào)文段數(shù)據(jù)部分的序號(hào)為 v。 -
ack=u+1
:服務(wù)器 B 期望收到客戶機(jī) A 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 u+1 開始的,同時(shí)確認(rèn)客戶機(jī) A 的連接釋放報(bào)文段(seq=u)已收到。 -
FIN=0
:TCP 確認(rèn)報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 0。 -
ACK=1
:當(dāng) FIN=0,ACK=1 時(shí),表明這是一個(gè)普通的 TCP 確認(rèn)報(bào)文段。
此時(shí),服務(wù)器 B 進(jìn)入 CLOSE-WAIT(關(guān)閉等待)狀態(tài)??蛻魴C(jī) A 已經(jīng)沒有數(shù)據(jù)要發(fā)送了。但服務(wù)器 B 如果還有數(shù)據(jù)要發(fā)送,客戶機(jī) A 仍要接收,即從服務(wù)器 B 到客戶機(jī) A 這個(gè)方向的連接并未關(guān)閉,這稱為半關(guān)閉狀態(tài),該狀態(tài)可能會(huì)持續(xù)一段時(shí)間。
3.2.3 服務(wù)器向客戶機(jī)發(fā)送 TCP 連接釋放報(bào)文段
服務(wù)器 B 向客戶機(jī) A 發(fā)送若干個(gè) TCP 確認(rèn)報(bào)文段,直到發(fā)送最后一次報(bào)文段,即 TCP 連接釋放報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=w, ack=u+1, FIN=1, ACK=1 | FIN 報(bào)文段可攜帶也可不攜帶數(shù)據(jù) |
-
seq=w
:經(jīng)過發(fā)送若干個(gè) TCP 確認(rèn)報(bào)文段,服務(wù)器 B 的 TCP 報(bào)文段數(shù)據(jù)部分的序號(hào)變?yōu)?w。 -
ack=u+1
:服務(wù)器 B 期望收到客戶機(jī) A 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 u+1 開始的,同時(shí)重復(fù)確認(rèn)客戶機(jī) A 的連接釋放報(bào)文段(seq=u)已收到。 -
FIN=1
:TCP 連接釋放報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 1。 -
ACK=1
:當(dāng) FIN=1,ACK=1 時(shí),表明這是一個(gè) TCP 連接釋放報(bào)文段。
此時(shí),服務(wù)器 B 進(jìn)入 LAST-ACK(最后確認(rèn))狀態(tài)。
3.2.4 客戶機(jī)向服務(wù)器發(fā)送 TCP 確認(rèn)報(bào)文段
客戶機(jī) A 收到 TCP 連接釋放報(bào)文段后,向服務(wù)器 B 發(fā)送 TCP 確認(rèn)報(bào)文段:
首部 | 數(shù)據(jù)部分 |
---|---|
seq=u+1, ack=w+1, FIN=0, ACK=1 | TCP 確認(rèn)報(bào)文段可以攜帶數(shù)據(jù) |
-
seq=u+1
:客戶機(jī) A 的 TCP 報(bào)文段數(shù)據(jù)部分的序號(hào)為 u+1。 -
ack=w+1
:客戶機(jī) A 期望收到服務(wù)器 B 發(fā)來的下一個(gè)報(bào)文段的數(shù)據(jù)部分序號(hào)是從 w+1 開始的,同時(shí)確認(rèn)服務(wù)器 B 的連接釋放報(bào)文段(seq=w)已收到。 -
FIN=0
:TCP 確認(rèn)報(bào)文段中的同步標(biāo)志位 SYN 的值必須設(shè)置為 0。 -
ACK=1
:當(dāng) FIN=0,ACK=1 時(shí),表明這是一個(gè)普通的 TCP 確認(rèn)報(bào)文段。
此時(shí),客戶機(jī) A 進(jìn)入 TIME-WAIT(時(shí)間等待)狀態(tài),服務(wù)器 B 收到 TCP 確認(rèn)報(bào)文段后進(jìn)入CLOSED(連接關(guān)閉)狀態(tài)。但是 TCP 連接仍未釋放,必須經(jīng)過 2MSL(最長報(bào)文段壽命,Maximum Segment Lifetime)的時(shí)間后,客戶機(jī) A 才能進(jìn)入 CLOSED(連接關(guān)閉)狀態(tài)。
【總結(jié)】TCP 釋放連接的過程:
客戶機(jī):“我準(zhǔn)備走了?!?服務(wù)器:“等一下,我還有一些話沒說完。blablabla”
服務(wù)器:“blablabla”
服務(wù)器:“blablabla,我說完了,你可以走了?!?客戶機(jī):“好的!那我走了!”
4 TCP 流量控制和可靠傳輸
TCP 協(xié)議提供一種基于滑動(dòng)窗口協(xié)議的流量控制機(jī)制。TCP 使用了校驗(yàn)、序號(hào)、確認(rèn)和重傳等機(jī)制來達(dá)到可靠傳輸?shù)哪康?,在下面的過程中將體現(xiàn)這一特點(diǎn)。
假設(shè)有發(fā)送方 A 和接收方 B 已建立 TCP 連接,不考慮 TCP 的擁塞控制。再假定 A 只給 B 發(fā)送數(shù)據(jù),B 對(duì) A 進(jìn)行流量控制。
在 A 和 B 建立 TCP 連接后,B 告訴 A:“我的接收窗口 rwnd=500”,因此 A 將自己的發(fā)送窗口 swnd 也設(shè)置為 500。窗口大小是以最大報(bào)文段 MSS 為單位的,一般將 MSS 設(shè)置為 1B,所以 “swnd=500”意思是發(fā)送窗口的大小為 500B。
A 的發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | √ | √ | √ | √ | √ | |||
A 已發(fā)送 | ||||||||
B 已確認(rèn) | ||||||||
B 已收到 |
A 發(fā)送數(shù)據(jù):seq=1,seq=101,seq=201,seq=301,發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | √ | √ | √ | √ | √ | |||
A 已發(fā)送 | √ | √ | √ | √ | ||||
B 已確認(rèn) | ||||||||
B 已收到 |
4.1 接收方對(duì)發(fā)送方的第 1 次流量控制
但是很不巧,seq=201 丟失了,B 只收到 seq=1,seq=101,seq=301。其中 seq=301 是失序報(bào)文段,但 B 不會(huì)丟棄它。TCP 作如下規(guī)定:每接收到一個(gè)失序報(bào)文段,就要發(fā)送一次冗余 ACK,指明下一個(gè)期待的報(bào)文數(shù)據(jù)序號(hào)。
很明顯,現(xiàn)在 B 期望收到 seq=201 的報(bào)文,因此 seq=301 是不會(huì)被確認(rèn)的,這被稱為累積確認(rèn)?,F(xiàn)在 B 的接收窗口已經(jīng)接受了 200B 的數(shù)據(jù),還有 300B 未接收,于是發(fā)送 ACK=1,ack=201,rwnd=300 的冗余報(bào)文給 A。
此時(shí)發(fā)送方 A 的 swnd 調(diào)整為 300,swnd 滑動(dòng)到首個(gè)未確認(rèn)的數(shù)據(jù)位置。發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | √ | √ | √ | |||||
A 已發(fā)送 | √ | √ | √ | √ | ||||
B 已確認(rèn) | √ | √ | ||||||
B 已收到 | √ | √ | √ |
發(fā)送方 A 繼續(xù)發(fā)送 seq=401,對(duì)于接收方 B 來說,seq=401 依然是失序報(bào)文段,繼續(xù)發(fā)送 ACK=1,ack=201,rwnd=300 的冗余報(bào)文給 A。此時(shí)發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | √ | √ | √ | |||||
A 已發(fā)送 | √ | √ | √ | √ | √ | |||
B 已確認(rèn) | √ | √ | ||||||
B 已收到 | √ | √ | √ | √ |
4.2 接收方對(duì)發(fā)送方的第 2 次流量控制
發(fā)送方 A 也沒有對(duì) seq=201 坐視不理,實(shí)質(zhì)上從發(fā)出 seq=201 開始,重傳計(jì)時(shí)器也開始計(jì)數(shù)了,A 發(fā)現(xiàn)計(jì)時(shí)器超時(shí)但仍未收到來自 B 的確認(rèn),于是進(jìn)行超時(shí)重傳。
【注】其實(shí),當(dāng)發(fā)送方 A 連續(xù)收到三個(gè)冗余 ACK 后,就可以立即重新發(fā)送 seq=201,而不必等待計(jì)時(shí)器超時(shí),這被稱為快重傳算法,在下一節(jié)“擁塞控制”將提到。
接收方 B 收到 seq=201 后,由于網(wǎng)絡(luò)流量原因,接收窗口需減小到 100B,于是返回 ACK=1,ack=501,rwnd=100 的報(bào)文。此時(shí)發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | √ | |||||||
A 已發(fā)送 | √ | √ | √ | √ | √ | |||
B 已確認(rèn) | √ | √ | √ | √ | √ | |||
B 已收到 | √ | √ | √ | √ | √ |
發(fā)送方 A 發(fā)送 seq=501,此時(shí)發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | √ | |||||||
A 已發(fā)送 | √ | √ | √ | √ | √ | √ | ||
B 已確認(rèn) | √ | √ | √ | √ | √ | |||
B 已收到 | √ | √ | √ | √ | √ |
4.3 接收方對(duì)發(fā)送方的第 3 次流量控制
接收方 B 收到 seq=501 后,返回 ACK=1,ack=601,rwnd=0 的報(bào)文,表示 B 不再接收任何數(shù)據(jù)。此時(shí)發(fā)送緩沖區(qū)情況如下:
數(shù)據(jù) | 1~100B | 101~200B | 201~300B | 301~400B | 401~500B | 501~600B | 601~700B | 701~800B |
---|---|---|---|---|---|---|---|---|
swnd | ||||||||
A 已發(fā)送 | √ | √ | √ | √ | √ | √ | ||
B 已確認(rèn) | √ | √ | √ | √ | √ | √ | ||
B 已收到 | √ | √ | √ | √ | √ | √ |
由于發(fā)送方 A 的 swnd=0,因此 A 不能發(fā)送任何數(shù)據(jù)了。接收方 B 必須發(fā)送一個(gè)非零窗口通知,以告知發(fā)送方 A:“你可以開始發(fā)送大小為 xxx 的窗口了?!彼?,A 一直在等待這個(gè)通知,只要收到通知,將恢復(fù)傳輸過程。
然而可能會(huì)出現(xiàn)這樣一種情況:B 發(fā)出的通知丟失,A 只能無限等待下去。為了打破由于非零窗口通知報(bào)文段丟失而引起的雙方互相等待的死鎖局面,TCP 為每一個(gè)連接都設(shè)有一個(gè)持續(xù)計(jì)時(shí)器:
- 只要 TCP 連接的一方收到對(duì)方的零窗口通知,就啟動(dòng)持續(xù)計(jì)時(shí)器。
- 當(dāng)持續(xù)計(jì)時(shí)器超時(shí)時(shí),就發(fā)送一個(gè)零窗口探測(cè)報(bào)文段,僅攜帶 1 字節(jié)的數(shù)據(jù)。
- 對(duì)方在確認(rèn)這個(gè)零窗口探測(cè)報(bào)文段時(shí),給出自己現(xiàn)在的接收窗口值 rwnd。
- 如果接收窗口值 rwnd 仍然是 0,那么收到這個(gè)報(bào)文段的一方就重新啟動(dòng)持續(xù)計(jì)時(shí)器,繼續(xù)以上過程。
- 如果接收窗口值 rwnd 不是 0,那么死鎖的局面就可以被打破了。
【注】TCP 規(guī)定:即使接收窗口值為 0,也必須接受零窗口探測(cè)報(bào)文段、確認(rèn)報(bào)文段以及攜帶有緊急數(shù)據(jù)的報(bào)文段。
5 TCP 擁塞控制
5.1 慢開始和擁塞避免
設(shè)置一個(gè)慢開始門限閾值 ssthresh,初始值為 16。根據(jù)發(fā)送方的擁塞窗口 cwnd 的大小執(zhí)行不同的算法:
- 當(dāng) cwnd < ssthresh 時(shí),使用慢開始算法;
- 當(dāng) cwnd > ssthresh 時(shí),使用擁塞避免算法;
- 當(dāng) cwnd = ssthresh 時(shí),使用擁塞避免算法。
慢開始算法:從 cwnd=1 開始,每經(jīng)過一個(gè)傳輸輪次(即往返時(shí)延 RTT)指數(shù)規(guī)律增長,cwnd=2,cwnd=4,cwnd=8,當(dāng) cwnd = ssthresh = 16 時(shí),改用擁塞避免算法。
擁塞避免算法:每經(jīng)過一個(gè)傳輸輪次(即往返時(shí)延 RTT),cwnd 加 1,即線性規(guī)律增長。只要發(fā)送方判斷網(wǎng)絡(luò)出現(xiàn)擁塞,則令 ssthresh = cwnd / 2。然后令 cwnd=1,重新執(zhí)行慢算法。
【注】傳輸輪次和往返時(shí)延的區(qū)別:
- 傳輸輪次:發(fā)送一批報(bào)文段并收到它們的確認(rèn)的時(shí)間。
- 往返時(shí)延 RTT:開始發(fā)送一批報(bào)文段到開始發(fā)送下一批報(bào)文段的時(shí)間。
例如有以下傳輸過程:
傳輸輪次 | cwnd | 發(fā)送的 TCP 數(shù)據(jù)部分的序號(hào) | 算法 | 備注 |
---|---|---|---|---|
1 | 1 | 0 號(hào) | 慢開始 | 初始時(shí),cwnd = 1,ssthresh = 16 |
2 | 2 | 1 ~ 2 號(hào) | 慢開始 | |
3 | 4 | 3 ~ 6 號(hào) | 慢開始 | |
4 | 8 | 7 ~ 14 號(hào) | 慢開始 | |
5 | 16 | 15 ~ 30 號(hào) | 擁塞避免 | cwnd = ssthresh = 16 |
6 | 17 | 31 ~ 47 號(hào) | 擁塞避免 | |
7 | 18 | 48 ~ 64 號(hào) | 擁塞避免 | |
… | … | … | ||
13 | 24 | 171 ~ 194 號(hào) | 擁塞避免 | 重傳計(jì)時(shí)器發(fā)生超時(shí),說明網(wǎng)絡(luò)擁塞,ssthresh = cwnd/2 = 12 |
14 | 1 | 195 號(hào) | 慢開始 | cwnd 重新設(shè)置為 1 |
15 | 2 | 196 ~ 197 號(hào) | 慢開始 | |
16 | 4 | 198 ~ 201 號(hào) | 慢開始 | |
17 | 8 | 202 ~ 209 號(hào) | 慢開始 | |
18 | 12 | 210 ~ 221 號(hào) | 擁塞避免 | cwnd = 16 > ssthresh = 12,改用擁塞避免算法 |
19 | 13 | 222 ~ 234 號(hào) | 擁塞避免 | |
… | … | … |
慢開始和擁塞避免算法的實(shí)現(xiàn)過程如下圖:
【注】慢開始和擁塞避免的含義:
- “慢開始”是指一開始向網(wǎng)絡(luò)注入的報(bào)文段少,而并不是指擁塞窗口 cwnd 的值增長速度慢。
- “擁塞避免”也并非指完全能夠避免擁塞,而是指在擁塞避免階段將 cwnd 值控制為按線性規(guī)律增長,使網(wǎng)絡(luò)比較不容易出現(xiàn)擁塞。
5.2 快重傳和快恢復(fù)
快重傳和快恢復(fù)是對(duì)慢開始和擁塞避免算法的改進(jìn)。根據(jù)發(fā)送方的擁塞窗口 cwnd 的大小執(zhí)行不同的算法:
- 當(dāng) cwnd < ssthresh 時(shí),若是首次傳輸,則使用慢開始算法;如果不是首次傳輸,則使用擁塞避免算法;
- 當(dāng) cwnd > ssthresh 時(shí),使用擁塞避免算法;
- 當(dāng) cwnd = ssthresh 時(shí),使用擁塞避免算法。
快重傳算法:當(dāng)發(fā)送方連續(xù)接收到三個(gè)冗余 ACK 報(bào)文時(shí),直接重傳對(duì)方尚未收到的報(bào)文段,而不必等待該報(bào)文段的重傳計(jì)時(shí)器超時(shí)。
快恢復(fù)算法:當(dāng)發(fā)送方連續(xù)接收到三個(gè)冗余 ACK 報(bào)文時(shí),令 ssthresh = cwnd / 2,然后 cwnd 從該 ssthresh 開始線性增加。
例如有以下傳輸過程:
傳輸輪次 | cwnd | 發(fā)送的 TCP 數(shù)據(jù)部分的序號(hào) | 算法 | 備注 |
---|---|---|---|---|
1 | 1 | 0 號(hào) | 慢開始 | 初始時(shí),cwnd = 1,ssthresh = 16 |
2 | 2 | 1 ~ 2 號(hào) | 慢開始 | |
3 | 4 | 3 ~ 6 號(hào) | 慢開始 | |
4 | 8 | 7 ~ 14 號(hào) | 慢開始 | |
5 | 16 | 15 ~ 30 號(hào) | 擁塞避免 | cwnd = ssthresh = 16 |
6 | 17 | 31 ~ 47 號(hào) | 擁塞避免 | |
7 | 18 | 48 ~ 64 號(hào) | 擁塞避免 | |
… | … | … | ||
13 | 24 | 171 ~ 194 號(hào) | 擁塞避免 | 發(fā)送方連續(xù)收到三個(gè)冗余 ACK 報(bào)文,說明網(wǎng)絡(luò)擁塞,ssthresh = cwnd/2 = 12 |
14 | 12 | 195 ~ 206 號(hào) | 擁塞避免 | cwnd 設(shè)置為 ssthresh = 12 |
15 | 13 | 207 ~ 219 號(hào) | 擁塞避免 | |
16 | 14 | 220 ~ 233 號(hào) | 擁塞避免 | |
17 | 15 | 234 ~ 248 號(hào) | 擁塞避免 | |
18 | 16 | 249 ~ 264 號(hào) | 擁塞避免 | |
19 | 17 | 265 ~ 281 號(hào) | 擁塞避免 | |
… | … | … |
快重傳和快恢復(fù)算法的實(shí)現(xiàn)過程如下圖:
文章來源:http://www.zghlxwxcb.cn/news/detail-412382.html
需要注意,發(fā)送方的發(fā)送窗口由接收方的接收窗口和發(fā)送方的擁塞窗口兩者的最小值所決定,即swnd = min(rwnd, cwnd)
。文章來源地址http://www.zghlxwxcb.cn/news/detail-412382.html
到了這里,關(guān)于【計(jì)算機(jī)網(wǎng)絡(luò)-傳輸層】TCP 協(xié)議的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!