人人妻人人澡人人爽人人精品av_精品乱码一区内射人妻无码_老司机午夜福利视频_精品成品国色天香摄像头_99精品福利国产在线导航_野花社区在线观看视频_大地资源在线影视播放_东北高大肥胖丰满熟女_金门瓶马车内剧烈运动

首頁(yè)>國(guó)內(nèi) > 正文

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

2023-08-11 11:23:24來(lái)源:Java極客技術(shù)

一、摘要

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

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


(相關(guān)資料圖)

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

話(huà)不多說(shuō),直接上干貨!

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

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

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

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

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

總的來(lái)說(shuō),TCP 協(xié)議是通過(guò)序列號(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)程,一般來(lái)講,通過(guò)端口號(hào)和IP地址,可以唯一確定一個(gè) TCP 連接,在網(wǎng)絡(luò)編程中,通常被稱(chēng)為一個(gè) socket 接口。序號(hào):Seq 序號(hào),占 4 個(gè)字節(jié)。用來(lái)標(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 首部長(zhǎng)度。保留字段:占 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í)用來(lái)同步序號(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)過(guò) 3 個(gè)階段:創(chuàng)建連接、數(shù)據(jù)傳送和釋放連接,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接、然后傳輸數(shù)據(jù)、最后斷開(kāi)連接,它保證兩臺(tái)計(jì)算機(jī)之間比較可靠的數(shù)據(jù)傳輸。

2.1、創(chuàng)建連接

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

圖片

詳細(xì)過(guò)程如下:

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

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

2.2、釋放連接

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

圖片

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

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

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

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

圖片

通過(guò)序列號(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ì)這種問(wèn)題,TCP 使用了重傳機(jī)制來(lái)解決。

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

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

常見(jiàn)的重傳方式有以下幾種:

超時(shí)重傳快速重傳SACKD-SACK3.1、超時(shí)重傳

超時(shí)重傳,顧名思義,就是在發(fā)送數(shù)據(jù)時(shí),設(shè)定一個(gè)定時(shí)器,當(dāng)超過(guò)指定的時(shí)間后,沒(méi)有收到對(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í)間如何來(lái)設(shè)定的問(wèn)題。

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

圖片

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

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

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

圖片

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

圖片

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

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

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

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

首先對(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í)際算出來(lái)的超時(shí)重傳時(shí)間RTO的值應(yīng)該略大于報(bào)文往返RTT的值。

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

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

3.2、快速重傳

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

快速重傳就是來(lái)補(bǔ)充超時(shí)重傳機(jī)制中時(shí)間過(guò)長(zhǎng)的問(wèn)題。

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

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

大致的工作方式,可以用如下圖來(lái)描述!

圖片

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

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

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

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

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

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

3.3、SACK 方法

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

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

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

圖片

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

3.4、Duplicate SACK 方法

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

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

圖片

過(guò)程分析:

發(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 可以稱(chēng)為D-SACK。當(dāng)發(fā)送方知道數(shù)據(jù)沒(méi)有丟,是接收方的 ACK 確認(rèn)報(bào)文丟了,就不會(huì)繼續(xù)重發(fā)數(shù)據(jù)包了

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

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

四、滑動(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è)人打電話(huà),你說(shuō)了一句話(huà),只有等到對(duì)方回復(fù)了你,你才能說(shuō)下一句,這顯然不現(xiàn)實(shí)。

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

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

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

圖片

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

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

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

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

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

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

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

圖片

含義解釋?zhuān)?/p>#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ā)送但總大小超過(guò)接收方處理范圍:52 字節(jié)以后

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

圖片

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

圖片

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

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

圖片

含義解釋?zhuān)?/p>SND.WND:表示發(fā)送窗口的大?。ù笮∈怯山邮辗街付ǖ模㏒ND.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ì)指針,通過(guò)SND.WND - (SND.NXT - SND.UNA)公式計(jì)算得來(lái)4.2、接受方的滑動(dòng)窗口

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

圖片

含義解釋?zhuān)?/p>#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ā)送來(lái)的下一個(gè)數(shù)據(jù)字節(jié)的序列號(hào),也就是#3的第一個(gè)字節(jié)可接受數(shù)據(jù)的最大值位置:它可以通過(guò)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è)傳輸過(guò)程可以用如下圖來(lái)描述。

圖片

上圖中的 ACK 600 確認(rèn)應(yīng)答報(bào)文丟失,也不會(huì)影響數(shù)據(jù)傳輸,因?yàn)榭梢酝ㄟ^(guò)下一個(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ù),就是窗口大小。

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

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

除此之外,計(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ù)填滿(mǎn)整個(gè)網(wǎng)絡(luò),我們把這一行為稱(chēng)為擁塞控制。

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

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

關(guān)鍵詞:

相關(guān)新聞

Copyright 2015-2020   三好網(wǎng)  版權(quán)所有 聯(lián)系郵箱:435 22 [email protected]  備案號(hào): 京ICP備2022022245號(hào)-21