自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TCP 滑動(dòng)窗口原理解析

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
計(jì)算機(jī)之間使用 TCP 協(xié)議進(jìn)行傳輸數(shù)據(jù)時(shí),每次連接都需要經(jīng)過 3 個(gè)階段:創(chuàng)建連接、數(shù)據(jù)傳送和釋放連接,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接、然后傳輸數(shù)據(jù)、最后斷開連接,它保證兩臺(tái)計(jì)算機(jī)之間比較可靠的數(shù)據(jù)傳輸。

一、摘要

前些日子,在分享網(wǎng)絡(luò)編程知識(shí)文章的時(shí)候,有個(gè)網(wǎng)友私信給我留言了一條“能不能寫一篇關(guān)于 TCP 滑動(dòng)窗口原理的文章”。

當(dāng)時(shí)沒有立即回復(fù),經(jīng)過查詢多方資料,發(fā)現(xiàn)這個(gè) TCP 真的非常非常的復(fù)雜,就像一個(gè)清澈的小溝,你以為很淺,結(jié)果一腳踩下去,感覺深不可測。

雖然之前也總結(jié)過一些關(guān)于網(wǎng)絡(luò)編程相關(guān)的技術(shù)知識(shí),對(duì)于 TCP 協(xié)議棧也做過一些介紹,但是大體上都描述的比較簡單,沒有深入去了解,本篇在很大程度上彌補(bǔ)了我對(duì)計(jì)算機(jī)網(wǎng)絡(luò)知識(shí)的空白。

話不多說,直接上干貨!

二、TCP 數(shù)據(jù)傳輸

在之前的文章中我們了解到,TCP 協(xié)議能保證網(wǎng)絡(luò)上的計(jì)算機(jī)之間可靠無差錯(cuò)的數(shù)據(jù)傳輸,比如上傳文件、下載文件、瀏覽網(wǎng)頁等都得益于它,實(shí)際的應(yīng)用場景非常廣泛。

與 TCP 協(xié)議一并稱霸天下的還有 UDP 協(xié)議,不過 UDP 協(xié)議雖然傳輸效率更高,但是并不保證數(shù)據(jù)傳輸正確性,相比 TCP 要稍遜一些。

事實(shí)上,TCP 協(xié)議經(jīng)過多年的發(fā)展,已經(jīng)成為實(shí)現(xiàn)數(shù)據(jù)可靠傳輸?shù)臉?biāo)準(zhǔn)協(xié)議,所謂可靠,就是確保數(shù)據(jù)準(zhǔn)確的、不重復(fù)、無延遲的到達(dá)目的地,那 TCP 協(xié)議是如何實(shí)現(xiàn)這些特點(diǎn)的呢?

其實(shí)要實(shí)現(xiàn)數(shù)據(jù)可靠傳輸,并不簡單,因?yàn)橐紤]異常的情況比較多,例如數(shù)據(jù)丟失、數(shù)據(jù)順序混亂、網(wǎng)絡(luò)擁堵等,如果不能解決這些問題,也就無從談起可靠傳輸。

總的來說,TCP 協(xié)議是通過序列號(hào)、確認(rèn)應(yīng)答、重發(fā)控制、連接管理以及窗口控制等機(jī)制實(shí)現(xiàn)數(shù)據(jù)穩(wěn)定可靠性的傳輸。

以下是 TCP 協(xié)議的報(bào)文格式。

圖片圖片

TCP 報(bào)文段包括協(xié)議首部和數(shù)據(jù)兩部分,協(xié)議首部的固定部分是 20 個(gè)字節(jié),頭部是固定部分,后面是選項(xiàng)部分。

下面是報(bào)文段首部各個(gè)字段的含義:

  • 源端口號(hào)以及目的端口號(hào):各占 2 個(gè)字節(jié),端口是傳輸層和應(yīng)用層的服務(wù)接口,用于尋找發(fā)送端和接收端的進(jìn)程,一般來講,通過端口號(hào)和IP地址,可以唯一確定一個(gè) TCP 連接,在網(wǎng)絡(luò)編程中,通常被稱為一個(gè) socket 接口。
  • 序號(hào):Seq 序號(hào),占 4 個(gè)字節(jié)。用來標(biāo)識(shí)從 TCP 發(fā)送端向 TCP 接收端發(fā)送的數(shù)據(jù)字節(jié)流序號(hào),發(fā)起方發(fā)送數(shù)據(jù)時(shí)對(duì)此進(jìn)行標(biāo)記。
  • 確認(rèn)序號(hào):Ack 序號(hào),占 4 個(gè)字節(jié),包含接受端所期望收到的下一個(gè)序號(hào)。只有 ACK 標(biāo)記位為 1 時(shí),確認(rèn)序號(hào)字段才有效,因此,確認(rèn)序號(hào)應(yīng)該是上次已經(jīng)成功收到數(shù)據(jù)字節(jié)序號(hào)加 1,即 Ack = Seq + 1。
  • 數(shù)據(jù)偏移:占 4 個(gè)字節(jié),用于指出 TCP 首部長度。
  • 保留字段:占 6 位,暫時(shí)可忽略,值全為 0。
  • 六位標(biāo)志位:值內(nèi)容含義如下

URG(緊急):為1時(shí)表明緊急指針字段有效

ACK(確認(rèn)):為1時(shí)表明確認(rèn)號(hào)字段有效

PSH(推送):為1時(shí)接收方應(yīng)盡快將這個(gè)報(bào)文段交給應(yīng)用層

RST(復(fù)位):為1時(shí)表明TCP連接出現(xiàn)故障必須重建連接

SYN(同步):在連接建立時(shí)用來同步序號(hào)

FIN(終止):為1時(shí)表明發(fā)送端數(shù)據(jù)發(fā)送完畢要求釋放連接

  • 窗口:占 2 個(gè)字節(jié),用于流量控制和擁塞控制,表示當(dāng)前接收緩沖區(qū)的大小。
  • 校驗(yàn)和:占 2 個(gè)字節(jié),范圍包括首部和數(shù)據(jù)兩部分
  • 緊急指針:指出了緊急數(shù)據(jù)的末尾在報(bào)文段中的位置,和 URG 搭配使用
  • 選項(xiàng)和填充:是可選的,默認(rèn)情況是不選。

計(jì)算機(jī)之間使用 TCP 協(xié)議進(jìn)行傳輸數(shù)據(jù)時(shí),每次連接都需要經(jīng)過 3 個(gè)階段:創(chuàng)建連接、數(shù)據(jù)傳送和釋放連接,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接、然后傳輸數(shù)據(jù)、最后斷開連接,它保證兩臺(tái)計(jì)算機(jī)之間比較可靠的數(shù)據(jù)傳輸。

2.1、創(chuàng)建連接

當(dāng)兩個(gè)設(shè)備之間準(zhǔn)備傳輸數(shù)據(jù)之前,TCP 會(huì)建立連接,創(chuàng)建連接的階段需要三次握手,過程如下:

圖片圖片

詳細(xì)過程如下:

  • 第一次握手:客戶端向服務(wù)器端發(fā)出連接請(qǐng)求,等待服務(wù)器確認(rèn)
  • 第二次握手:服務(wù)器端收到請(qǐng)求后,向客戶端回送一個(gè)確認(rèn),通知客戶端收到了連接請(qǐng)求
  • 第三次握手:客戶端再次向服務(wù)器端發(fā)送確認(rèn)信息,確認(rèn)連接

完成以上 3 次握手之后,可靠性連接建立完成,就可以進(jìn)行數(shù)據(jù)傳輸了。

2.2、釋放連接

當(dāng)數(shù)據(jù)傳輸完畢之后,TCP 會(huì)釋放連接,連接的釋放需要四次揮手,過程如下:

圖片圖片

  • 第一次揮手:客戶端向服務(wù)器端發(fā)出請(qǐng)求切斷連接,等待服務(wù)器確認(rèn)
  • 第二次揮手:服務(wù)器端收到請(qǐng)求后,向客戶端回送一個(gè)確認(rèn)信息,并同意關(guān)閉請(qǐng)求
  • 第三次揮手:服務(wù)器端再次向客戶端發(fā)出請(qǐng)求切斷連接,等待客戶端確認(rèn)
  • 第四次揮手:客戶端收到請(qǐng)求后,向服務(wù)器端回送一個(gè)確認(rèn)信息,并同意關(guān)閉請(qǐng)求

完成以上 4 次揮手之后,連接釋放完成。

2.3、數(shù)據(jù)傳輸過程

通過以上的介紹,我們可以描繪出一個(gè)簡易版的 TCP 數(shù)據(jù)傳輸過程,如下圖所示。

圖片圖片

通過序列號(hào)與確認(rèn)應(yīng)答機(jī)制,是 TCP 實(shí)現(xiàn)數(shù)據(jù)可靠傳輸?shù)姆绞街?,也是最為重要的基石?/p>

但是在復(fù)雜的網(wǎng)絡(luò)環(huán)境下,并不一定能如上圖所描述的那樣順利的進(jìn)行數(shù)據(jù)傳輸,例如數(shù)據(jù)包丟失,針對(duì)這種問題,TCP 使用了重傳機(jī)制來解決。

三、重傳機(jī)制介紹

當(dāng)網(wǎng)絡(luò)不穩(wěn)定的時(shí)候,很容易出現(xiàn)數(shù)據(jù)包丟失,TCP 采用了哪些重傳手段來解決數(shù)據(jù)包丟失問題呢?

常見的重傳方式有以下幾種:

  • 超時(shí)重傳
  • 快速重傳
  • SACK
  • D-SACK

3.1、超時(shí)重傳

超時(shí)重傳,顧名思義,就是在發(fā)送數(shù)據(jù)時(shí),設(shè)定一個(gè)定時(shí)器,當(dāng)超過指定的時(shí)間后,沒有收到對(duì)方的 ACK 確認(rèn)應(yīng)答報(bào)文,就會(huì)重發(fā)數(shù)據(jù)。

TCP 會(huì)在以下兩種情況發(fā)生超時(shí)重傳:

  • 發(fā)送的數(shù)據(jù)包丟失
  • 確認(rèn)應(yīng)答丟失

其中比較關(guān)鍵的就是超時(shí)重傳時(shí)間如何來設(shè)定的問題。

我們先來看看正常的數(shù)據(jù)傳輸過程。

圖片圖片

其中 RTT 指的是數(shù)據(jù)從網(wǎng)絡(luò)一端傳送到另一端所需的時(shí)間,也就是數(shù)據(jù)包發(fā)送出去的往返時(shí)間。

超時(shí)重傳時(shí)間,我們以 RTO (Retransmission Timeout 超時(shí)重傳時(shí)間)來表示。

當(dāng)超時(shí)重傳時(shí)間設(shè)定過大,會(huì)出現(xiàn)什么情況呢?如下圖所示

圖片圖片

當(dāng)超時(shí)重傳時(shí)間設(shè)定過小,又會(huì)出現(xiàn)什么情況呢?如下圖所示

圖片圖片

一路分析下來,可以得出如下結(jié)論:

  • 當(dāng)超時(shí)重發(fā)時(shí)間 RTO 設(shè)置較大時(shí),會(huì)出現(xiàn)數(shù)據(jù)傳輸效率差的現(xiàn)象,比如數(shù)據(jù)包丟失之后,需要等很長時(shí)間才重發(fā),性能差;
  • 當(dāng)超時(shí)重發(fā)時(shí)間 RTO 設(shè)置較小時(shí),可能會(huì)出現(xiàn)并沒有丟失包就重發(fā),多次重發(fā)會(huì)造成網(wǎng)絡(luò)擁堵,導(dǎo)致出現(xiàn)更多的超時(shí),更多的超時(shí)意味著更多的重發(fā);

因此可以得出一個(gè)結(jié)論,超時(shí)重發(fā)時(shí)間既不能設(shè)置過大,也不能設(shè)置過小,必須精準(zhǔn)的計(jì)算。

以 Linux 操作系統(tǒng)為例,RTO 的計(jì)算過程如下!

  • 首先對(duì) TCP 數(shù)據(jù)傳輸所需的往返時(shí)間,也就是 RTT 值進(jìn)行采樣,然后進(jìn)行加權(quán)平均,算出一個(gè)平滑 RTT 的值,同時(shí)這個(gè)值隨著網(wǎng)絡(luò)狀態(tài)會(huì)不斷的變化。
  • 除了采樣 RTT 值,還要記錄 RTT 的波動(dòng)變化,避免 RTT 的變化較大,難以發(fā)現(xiàn)

圖片圖片

其中SRTT是計(jì)算平滑的RTT ,DevRTR是計(jì)算平滑的RTT與最新RTT的差距,在 Linux 下,通常α = 0.125,β = 0.25,μ = 1,? = 4。

實(shí)際算出來的超時(shí)重傳時(shí)間RTO的值應(yīng)該略大于報(bào)文往返RTT的值。

如果超時(shí)重發(fā)的數(shù)據(jù),再次超時(shí)的時(shí)候,又需要重傳的時(shí)候,TCP 的策略是超時(shí)間隔加倍。

也就是說,每當(dāng)遇到一次超時(shí)重傳的時(shí)候,會(huì)將下一次超時(shí)時(shí)間間隔設(shè)為先前值的兩倍,多次超時(shí)說明網(wǎng)絡(luò)環(huán)境差,不宜頻繁反復(fù)重發(fā)。

3.2、快速重傳

超時(shí)重傳雖然能解決數(shù)據(jù)丟包的問題,但是超時(shí)重發(fā)時(shí)間有時(shí)候可能會(huì)較長,有沒有一種更快的重傳方式呢?

快速重傳就是來補(bǔ)充超時(shí)重傳機(jī)制中時(shí)間過長的問題。

簡單的說,快速重傳不像超時(shí)重傳那樣通過時(shí)間來驅(qū)動(dòng)重發(fā),而是通過次數(shù)來驅(qū)動(dòng)重發(fā)。

當(dāng)收到報(bào)文重復(fù)的 ACK 數(shù)量,到達(dá)一定的閥值(一般為3),TCP 會(huì)在定時(shí)器過期之前,檢查丟失的報(bào)文段并重傳丟失的報(bào)文段。

大致的工作方式,可以用如下圖來描述!

圖片圖片

在上圖,發(fā)送方向接受方發(fā)出了 1、2、3、4、5 份數(shù)據(jù),大致執(zhí)行的過程如下:

  • 第一份 Seq1 先送到了,接受方就 Ack 回 2,表示 seq 1 已經(jīng)收到,準(zhǔn)備接受下一個(gè)序列號(hào)為 2 的包
  • Seq2 因?yàn)槟承┰驔]收到,Seq3 到達(dá)了,因?yàn)?Seq2 缺失,還是 Ack 回 2
  • 后面的 Seq4 和 Seq5 都到了,因?yàn)?Seq2 沒有收到,還是 Ack 回 2
  • 發(fā)送端收到了三個(gè) Ack = 2 的確認(rèn),知道了 Seq2 還沒有收到,就會(huì)在定時(shí)器過期之前,重傳丟失的 Seq2
  • 最后接收方收到了 Seq2,此時(shí)因?yàn)?Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。

因此,快速重傳的工作方式是當(dāng)收到相同的 ACK 報(bào)文數(shù)量到達(dá)一個(gè)閥值,默認(rèn)是 3,會(huì)在定時(shí)器過期之前,重傳丟失的報(bào)文段。

快速重傳機(jī)制彌補(bǔ)了超時(shí)重傳機(jī)制中時(shí)間過長的問題,但是它依然面臨著另外一個(gè)問題,那就是重傳的時(shí)候,是重傳之前的一個(gè)還是重傳所有的包?

例如上面的例子,是重傳 Seq2 呢?還是重傳 Seq2、Seq3、Seq4、Seq5 呢?

根據(jù) TCP 不同的實(shí)現(xiàn),以上兩種情況都有可能。

3.3、SACK 方法

為了解決不知道該重傳哪些 TCP 報(bào)文,天才師們想出來了SACK方法,英文全稱:Selective Acknowledgment,也被稱為選擇性確認(rèn)。

具體實(shí)現(xiàn)就是需要在 TCP 頭部選項(xiàng)字段里加一個(gè) SACK 的東西,接受方可以將緩存的數(shù)據(jù)地圖發(fā)送給發(fā)送方,這樣發(fā)送方就可以知道哪些數(shù)據(jù)收到了,哪些數(shù)據(jù)沒收到,知道了這些信息,就可以只重傳丟失的數(shù)據(jù)。

如下圖,當(dāng)發(fā)送方收到了三次同樣的 ACK 確認(rèn)報(bào)文,于是就會(huì)觸發(fā)快速重發(fā)機(jī)制,通過 SACK 信息發(fā)現(xiàn)只有200~299這段數(shù)據(jù)丟失,會(huì)將丟失的片段進(jìn)行重發(fā),以便提升數(shù)據(jù)傳輸可靠性效率。

圖片圖片

需要主要的是,如果要支持 SACK 機(jī)制,必須發(fā)送方和接受方都要支持。在 Linux 操作系統(tǒng)中,開發(fā)者可以通過net.ipv4.tcp_sack參數(shù)打開這個(gè)功能(Linux 2.4 后默認(rèn)打開)。

3.4、Duplicate SACK 方法

最后再來講講 Duplicate SACK 方法,又稱D-SACK,這個(gè)方法實(shí)現(xiàn)主要是使用  SACK和ACK來告訴發(fā)送方有哪些數(shù)據(jù)被重復(fù)接收了,以防止 TCP 反復(fù)的重發(fā)。

我們用個(gè)案例來介紹D-SACK的作用,例如 ACK 丟包的場景,如下圖!

圖片圖片

過程分析:

  • 發(fā)送方向成功向接受方發(fā)送了兩個(gè)數(shù)據(jù)包,但是接受方發(fā)給發(fā)送方兩個(gè) ACK 確認(rèn)應(yīng)答都丟失了,發(fā)送方檢查超時(shí)后,重傳第一個(gè)數(shù)據(jù)包(100 ~ 199)
  • 接收方發(fā)現(xiàn)數(shù)據(jù)是重復(fù)收到的,于是回了一個(gè)ACK 300和 SACK 100~199,告訴發(fā)送方100~299的數(shù)據(jù)早已被接收了,因?yàn)?ACK 都到300了,因此這個(gè) SACK 可以稱為D-SACK。
  • 當(dāng)發(fā)送方知道數(shù)據(jù)沒有丟,是接收方的 ACK 確認(rèn)報(bào)文丟了,就不會(huì)繼續(xù)重發(fā)數(shù)據(jù)包了

使用D-SACK方法的好處,可以讓發(fā)送方知道,是發(fā)出去的包丟了還是接收方回應(yīng)的 ACK 包丟了,然后來決定是否需要繼續(xù)重發(fā)包。

在 Linux 操作系統(tǒng)下,可以通過net.ipv4.tcp_dsack參數(shù)來開啟/關(guān)閉這個(gè)功能(Linux 2.4 后默認(rèn)打開)。

四、滑動(dòng)窗口介紹

在上文中,我們有介紹到 TCP 協(xié)議的數(shù)據(jù)傳輸機(jī)制,當(dāng)兩臺(tái)計(jì)算機(jī)之間建立連接之后,就可以進(jìn)行傳輸數(shù)據(jù)了,TCP 每發(fā)送一個(gè)數(shù)據(jù),都要進(jìn)行一次確認(rèn)應(yīng)答,當(dāng)上一個(gè)數(shù)據(jù)包收到了應(yīng)答了, 再發(fā)送下一個(gè),從而保證數(shù)據(jù)的可靠傳輸。

圖片圖片

這種傳輸方式,雖然可靠但是缺點(diǎn)也比較明顯,傳輸數(shù)據(jù)的效率非常的低下,好比你現(xiàn)在跟某個(gè)人打電話,你說了一句話,只有等到對(duì)方回復(fù)了你,你才能說下一句,這顯然不現(xiàn)實(shí)。

為解決這個(gè)問題,TCP 引入了滑動(dòng)窗口,可以一次性向窗口中發(fā)送多個(gè)數(shù)據(jù)包并不需要依次等待接受方的確認(rèn)應(yīng)答,即使在往返時(shí)間較長的情況下,它也不會(huì)降低數(shù)據(jù)傳輸效率。

那什么是滑動(dòng)窗口呢?我們以高速路的收費(fèi)站為例,做一個(gè)類比介紹。

上過高速的同學(xué)應(yīng)該都知道,在高速路上有一個(gè)入口收費(fèi)站和一個(gè)出口收費(fèi)站。TCP 也是一樣的,除了入口有發(fā)送方滑動(dòng)窗口,出口處也設(shè)立有接收方滑動(dòng)窗口。

圖片圖片

對(duì)于發(fā)送方滑動(dòng)窗口,我們可以把數(shù)據(jù)包看成車輛,分類它們的狀態(tài):

  • 還未進(jìn)入入口收費(fèi)站的車輛:對(duì)應(yīng)的是上圖Not Sent,Recipient Not Ready to Receive部分,這些屬于發(fā)送端未發(fā)送,同時(shí)接收端也未準(zhǔn)備接收的數(shù)據(jù)
  • 已進(jìn)入收費(fèi)站但未進(jìn)入高速路的車輛:對(duì)應(yīng)的是上圖Not Sent,Recipient Ready to Receive部分,這些屬于發(fā)送端未發(fā)送,但已經(jīng)告知接收方的數(shù)據(jù),其實(shí)已經(jīng)在窗口中(發(fā)送端緩存)了,等待發(fā)送。
  • 在高速公路上行駛的車輛:對(duì)應(yīng)的是上圖Send But Not Yet Acknowledged部分,這些屬于發(fā)送端已發(fā)送出去,等到接收方接受的數(shù)據(jù),屬于窗口內(nèi)的數(shù)據(jù)。
  • 到達(dá)出口收費(fèi)站的車輛:對(duì)應(yīng)的是上圖Sent and Acknowledged部分,這些屬于已經(jīng)發(fā)送成功并已經(jīng)被接受的數(shù)據(jù),這些數(shù)據(jù)已經(jīng)離開窗口了。

同樣,對(duì)于接受方滑動(dòng)窗口,我們也可以把數(shù)據(jù)包看成車輛,分類它們的狀態(tài):

  • 還未到達(dá)出口收費(fèi)站的車輛:狀態(tài)為Not Received,表示還沒有被接收的數(shù)據(jù)。
  • 到達(dá)出口收費(fèi)站但未完成繳費(fèi)的車輛:狀態(tài)為Received Not ACK,表示已經(jīng)被接受但是還沒有回復(fù) ACK
  • 繳完費(fèi)并離開出口收費(fèi)站的車輛:狀態(tài)為Received and ACK,表示已經(jīng)被接受并回復(fù)了 ACK

通過以上的描述,相信大家對(duì)滑動(dòng)窗口已經(jīng)有了初步的認(rèn)識(shí),在整個(gè)數(shù)據(jù)傳輸過程中,光線傳輸類似于高速公路,滑動(dòng)窗口類似于收費(fèi)站,通過收費(fèi)站可以做到對(duì)車輛進(jìn)行適當(dāng)?shù)牧髁靠刂疲苑乐垢咚俟烦霈F(xiàn)擁堵,滑動(dòng)窗口也有同樣的作用。

4.1、發(fā)送方的滑動(dòng)窗口

下圖就是發(fā)送方的滑動(dòng)窗口樣例圖,根據(jù)處理的情況分成四個(gè)部分,其中深藍(lán)色方框是發(fā)送窗口,紫色方框是可用窗口。

圖片圖片

含義解釋:

  • #1表示已發(fā)送并收到 ACK 確認(rèn)的數(shù)據(jù):1~31 字節(jié)
  • #2表示已發(fā)送但未收到 ACK 確認(rèn)的數(shù)據(jù):32~45 字節(jié)
  • #3表示未發(fā)送但總大小在接收方處理范圍內(nèi):46~51字節(jié)
  • #4表示未發(fā)送但總大小超過接收方處理范圍:52 字節(jié)以后

當(dāng)發(fā)送方把數(shù)據(jù)全部都一下發(fā)送出去后,可用窗口的大小就為 0 了,表明可用窗口耗盡,在沒收到接受方 ACK 確認(rèn)之前是無法繼續(xù)發(fā)送數(shù)據(jù)的。

圖片圖片

當(dāng)收到之前發(fā)送的數(shù)據(jù)32~36字節(jié)的 ACK 確認(rèn)應(yīng)答后,如果發(fā)送窗口的大小沒有變化,則滑動(dòng)窗口往右邊移動(dòng) 5 個(gè)字節(jié),因?yàn)橛?5 個(gè)字節(jié)的數(shù)據(jù)被應(yīng)答確認(rèn),接下來52~56字節(jié)又變成了可用窗口,那么后續(xù)也就可以發(fā)送52~56這 5 個(gè)字節(jié)的數(shù)據(jù)了。

圖片圖片

程序是如何精準(zhǔn)的控制發(fā)送方的窗口數(shù)據(jù)呢?

TCP 滑動(dòng)窗口方案使用三個(gè)指針來跟蹤在四個(gè)傳輸類別中的每一個(gè)類別中的字節(jié)。其中兩個(gè)指針是絕對(duì)指針(指特定的序列號(hào)),一個(gè)是相對(duì)指針(需要做偏移)。

圖片圖片

含義解釋:

  • SND.WND:表示發(fā)送窗口的大?。ù笮∈怯山邮辗街付ǖ模?/li>
  • SND.UNA:是一個(gè)絕對(duì)指針,它指向的是已發(fā)送但未收到確認(rèn)的第一個(gè)字節(jié)的序列號(hào),也就是#2的第一個(gè)字節(jié)
  • SND.NXT:也是一個(gè)絕對(duì)指針,它指向未發(fā)送但可發(fā)送范圍的第一個(gè)字節(jié)的序列號(hào),也就是#3的第一個(gè)字節(jié)
  • 可用窗口大?。菏且粋€(gè)相對(duì)指針,通過SND.WND - (SND.NXT - SND.UNA)公式計(jì)算得來

4.2、接受方的滑動(dòng)窗口

接下來我們看看接收方的滑動(dòng)窗口,接收窗口相對(duì)簡單一些,根據(jù)處理的情況劃分成三個(gè)部分。

圖片圖片

含義解釋:

  • #1和#2表示已成功接收并確認(rèn)的數(shù)據(jù),等待應(yīng)用進(jìn)程讀取
  • #3表示未收到數(shù)據(jù)但可以接收的數(shù)據(jù)
  • #4表示未收到數(shù)據(jù)并不可以接收的數(shù)據(jù)

其中三個(gè)接收部分,使用兩個(gè)指針進(jìn)行劃分:

  • RCV.WND:表示接收窗口的大小,它會(huì)通告給發(fā)送方
  • RCV.NXT:是一個(gè)絕對(duì)指針,它指向期望從發(fā)送方發(fā)送來的下一個(gè)數(shù)據(jù)字節(jié)的序列號(hào),也就是#3的第一個(gè)字節(jié)
  • 可接受數(shù)據(jù)的最大值位置:它可以通過RCV.NXT + RCV.WND計(jì)算得出,也就是#4的第一個(gè)字節(jié)

五、小結(jié)

相比傳統(tǒng)的發(fā)送一個(gè)包,然后等待確認(rèn)應(yīng)答再發(fā)送包的數(shù)據(jù)傳輸模型,滑動(dòng)窗口這種一次性批量發(fā)包然后等待確認(rèn)應(yīng)答的傳輸方式,可以顯著的提升數(shù)據(jù)傳輸效率,整個(gè)傳輸過程可以用如下圖來描述。

圖片圖片

上圖中的 ACK 600 確認(rèn)應(yīng)答報(bào)文丟失,也不會(huì)影響數(shù)據(jù)傳輸,因?yàn)榭梢酝ㄟ^下一個(gè)確認(rèn)應(yīng)答進(jìn)行確認(rèn),只要發(fā)送方收到了 ACK 700 確認(rèn)應(yīng)答,就表示 700 之前的所有數(shù)據(jù)接收方都收到了,這種確認(rèn)應(yīng)答模式叫累計(jì)確認(rèn)或者累計(jì)應(yīng)答。

在上文中,我們提到滑動(dòng)窗口有一個(gè)很關(guān)鍵字的參數(shù),就是窗口大小。

通常,窗口的大小是由接收方來決定的,接收端告訴發(fā)送端自己還有多少緩沖區(qū)可以接收數(shù)據(jù),防止發(fā)送的數(shù)據(jù)量過大接受方處理不過來,會(huì)觸發(fā)發(fā)送方重發(fā)機(jī)制,從而導(dǎo)致網(wǎng)絡(luò)流量的無端的浪費(fèi)。

通過控制窗口大小,可以避免發(fā)送方的數(shù)據(jù)超過接收方的可用窗口,也就是大家常說的流量控制。

除此之外,計(jì)算機(jī)網(wǎng)絡(luò)都處在一個(gè)共享的環(huán)境,難免會(huì)出現(xiàn)網(wǎng)絡(luò)擁堵的現(xiàn)象。當(dāng)網(wǎng)絡(luò)出現(xiàn)擁堵時(shí),流量控制的手段非常有限。

如果網(wǎng)絡(luò)出現(xiàn)擁堵時(shí),發(fā)送方繼續(xù)發(fā)送大量數(shù)據(jù)包,可能會(huì)導(dǎo)致數(shù)據(jù)包時(shí)延、丟失等,這時(shí) TCP 就會(huì)重傳數(shù)據(jù),重傳就會(huì)導(dǎo)致網(wǎng)絡(luò)的負(fù)擔(dān)更重,于是會(huì)導(dǎo)致更大的延遲以及更多的丟包,此時(shí)可能會(huì)進(jìn)入惡性循環(huán)….

因此,TCP 不能忽略網(wǎng)絡(luò)上發(fā)生的事,當(dāng)網(wǎng)絡(luò)發(fā)生擁塞時(shí),TCP 需要降低發(fā)送的數(shù)據(jù)量,避免發(fā)送方的數(shù)據(jù)填滿整個(gè)網(wǎng)絡(luò),我們把這一行為稱為擁塞控制。

關(guān)于流量控制和擁塞控制的實(shí)現(xiàn),鑒于文章篇幅過長,我們會(huì)在下篇文章中進(jìn)行詳解。

本文整理了一些優(yōu)秀網(wǎng)友分享的知識(shí),在此特別感謝作者小林coding的圖解 tcp 滑動(dòng)窗口文章分享,給予了很大的知識(shí)幫助,同時(shí)結(jié)合自己的理解比較全面的探討了 TCP 滑動(dòng)窗口的原理,希望對(duì)大家有所幫助。

責(zé)任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2023-02-28 09:07:18

ChatGPTAI

2023-11-10 16:28:02

TCP窗口

2021-07-05 07:51:43

JVM底層Python

2015-01-15 09:21:24

TCP窗口

2019-12-06 10:59:20

JavaScript運(yùn)行引擎

2021-07-12 09:45:36

NameServer 核心Conusmer

2021-01-12 14:46:34

Kubernetes開發(fā)存儲(chǔ)

2013-11-18 10:04:31

TCP 滑動(dòng)窗口

2021-12-01 18:36:35

屬性

2020-05-21 13:25:43

Spring組件架構(gòu)

2024-06-27 08:26:10

LooperAndroid內(nèi)存

2010-07-06 10:07:10

jQueryJSON

2015-07-01 13:34:22

Kubernetes應(yīng)用部署模型

2021-06-16 15:18:03

鴻蒙HarmonyOS應(yīng)用

2015-08-18 09:40:32

OpenStack Neutron虛擬網(wǎng)絡(luò)

2023-11-16 09:01:37

Hadoop數(shù)據(jù)庫

2015-08-19 10:36:24

Zigbee技術(shù)無線通信

2024-10-12 10:29:11

計(jì)算機(jī)圖形

2018-07-05 14:25:01

TCP握手原理

2024-08-27 12:32:32

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)