個(gè)人主頁(yè):兜里有顆棉花糖
歡迎 點(diǎn)贊?? 收藏? 留言? 加關(guān)注??本文由 兜里有顆棉花糖 原創(chuàng)
收錄于專欄【網(wǎng)絡(luò)編程】【Java系列】
本專欄旨在分享學(xué)習(xí)網(wǎng)絡(luò)編程、計(jì)算機(jī)網(wǎng)絡(luò)的一點(diǎn)學(xué)習(xí)心得,歡迎大家在評(píng)論區(qū)交流討論??
??一、滑動(dòng)窗口原理
滑動(dòng)窗口可以保證在TCP可靠性傳輸?shù)那疤嵯拢瑪?shù)據(jù)傳輸?shù)男什粫?huì)太低。我們知道UDP協(xié)議是不支持可靠性傳輸?shù)?,所以UDP傳輸數(shù)據(jù)的效率是要高于TCP的;而TCP的滑動(dòng)窗口機(jī)制則可以縮小UDP和TCP傳輸效率之間的差距。
我們先來(lái)看看如果TCP如果不使用滑動(dòng)窗口機(jī)制的時(shí)候是怎樣進(jìn)行數(shù)據(jù)傳輸?shù)?,如下圖:
上面的傳輸雖然能夠數(shù)據(jù)傳輸?shù)目煽啃裕鋵?shí)主機(jī)A的大部分時(shí)間都消耗在等待ACK確認(rèn)應(yīng)答上了,所以數(shù)據(jù)傳輸?shù)男什⒉桓摺6瑒?dòng)窗口機(jī)制就可以縮短主機(jī)A等待ACK的等待時(shí)間,如下圖(使用滑動(dòng)窗口機(jī)制):
如上圖:滑動(dòng)窗口機(jī)制允許發(fā)送方在發(fā)送數(shù)據(jù)時(shí)能夠同時(shí)發(fā)送多個(gè)數(shù)據(jù)包,而無(wú)需等待確認(rèn),同時(shí)我們把一次能夠發(fā)送數(shù)據(jù)的多少稱之為窗口。
當(dāng)然了,窗口越大,數(shù)據(jù)傳輸?shù)男示驮礁撸谴翱诖笮∈遣荒軣o(wú)限大的,否則接收方或者中間過(guò)程的網(wǎng)絡(luò)設(shè)備是無(wú)法在一定時(shí)間內(nèi)處理如此龐大的數(shù)據(jù)的。
滑動(dòng)窗口如何解決丟包問(wèn)題
滑動(dòng)窗口機(jī)制在TCP協(xié)議中起到了提高數(shù)據(jù)傳輸效率的作用,那如果數(shù)據(jù)傳輸過(guò)程中丟包了又該怎么辦呢?這里的丟包問(wèn)題分為兩種情況:一定情況是要傳輸?shù)臄?shù)據(jù)丟失了;另外一種情況就是ACK丟失。接下來(lái)我們來(lái)分析滑動(dòng)窗口下的超時(shí)重傳過(guò)程。
-
情況一:ACK丟失
我們先來(lái)分析較為簡(jiǎn)單的一種情況,即滑動(dòng)窗口機(jī)制下,如果發(fā)送了ACK丟失,此時(shí)我們不需要對(duì)該情況作出任何處理。
請(qǐng)看上圖:上圖中ACK1001(注意1001是一個(gè)確認(rèn)序號(hào)哈,不要和ACK進(jìn)行混淆,這里只是為了表述所以才寫到一起)丟失了,但是ACK2001并沒(méi)有丟失,確認(rèn)序號(hào)2001的意思就是2000之前的所有數(shù)據(jù)(包括2000)都已經(jīng)接收到了,所以即使ACK1001丟失,主機(jī)A在接收到ACK2001之后也是可以確定1000之前的數(shù)據(jù)包括1000(準(zhǔn)確來(lái)收是2000之前的數(shù)據(jù))都已經(jīng)接收到了。
ACK3001和ACK4001也是一個(gè)道理。
如果所有的ACK全部丟失的話,這就相當(dāng)于重大的網(wǎng)絡(luò)故障了,另當(dāng)別論即可;否則如果只是丟失一部分的ACK的話,對(duì)于TCP可靠傳輸是沒(méi)有任何影響的。
- 情況二:數(shù)據(jù)包丟失
現(xiàn)在我們來(lái)看第二種情況,即數(shù)據(jù)包丟失:數(shù)據(jù)包如果丟失的話是一定要進(jìn)行數(shù)據(jù)重傳的。接下來(lái)我們對(duì)數(shù)據(jù)包什么時(shí)候重傳以及怎樣對(duì)數(shù)據(jù)包進(jìn)行重傳來(lái)進(jìn)行分析。
上圖中數(shù)據(jù)1001-2000
并沒(méi)有傳輸?shù)街鳈C(jī)B(即數(shù)據(jù)發(fā)生了丟失);接下來(lái)主機(jī)A發(fā)送了數(shù)據(jù)2001-3000
,傳輸成功之后我們發(fā)現(xiàn)主機(jī)B返回的確認(rèn)序號(hào)卻是1001;接下來(lái)數(shù)據(jù)3001-7000
傳輸成功之后返回的ACK確認(rèn)序號(hào)依舊是1001,意思就是主機(jī)B在向主機(jī)A索要1001-2000的數(shù)據(jù)
。換言之主機(jī)B只要沒(méi)有接收到1001-2000的數(shù)據(jù)的話,那么主機(jī)B就會(huì)一直向主機(jī)A索要1001-2000之間的數(shù)據(jù),具體做法是主機(jī)B一直返回確認(rèn)序號(hào)是1001的ACK
;與此同時(shí)當(dāng)主機(jī)A連續(xù)收到了多個(gè)確認(rèn)序號(hào)是1001的ACK之后,就會(huì)向主機(jī)B發(fā)送1001-2000的數(shù)據(jù)。
當(dāng)重傳的1001-2000的數(shù)據(jù)到達(dá)主機(jī)B之后,主機(jī)B返回的確認(rèn)序號(hào)就是7001。
我們站在緩沖區(qū)的角度來(lái)進(jìn)行分析:接收方主機(jī)B有一個(gè)緩沖區(qū)用來(lái)接收主機(jī)A發(fā)送的數(shù)據(jù),如下圖所示:
這里使用最小的成本來(lái)完成丟失數(shù)據(jù)的重新傳輸(并沒(méi)有重傳其它的數(shù)據(jù)),我們可以把它叫做快速重傳哈,其實(shí)這個(gè)快速重傳本質(zhì)上依舊是超時(shí)重傳,只不過(guò)是將把超時(shí)重傳結(jié)合滑動(dòng)窗口進(jìn)行了一個(gè)變形的操作。
這里要說(shuō)明以下,有時(shí)TCP協(xié)議并不會(huì)涉及到滑動(dòng)窗口的機(jī)制,即并不會(huì)使用快速重傳:當(dāng)網(wǎng)絡(luò)通信涉及到大規(guī)模數(shù)據(jù)傳輸?shù)臅r(shí)候,會(huì)使用滑動(dòng)窗口快速重傳的機(jī)制;當(dāng)網(wǎng)絡(luò)通信涉及到的數(shù)據(jù)很少的時(shí)候,此時(shí)就是使用超時(shí)重傳機(jī)制。TCP會(huì)根據(jù)具體的場(chǎng)景來(lái)決策到底是使用超時(shí)重傳還是快速重傳
。
??二、滑動(dòng)窗口——流量控制
我們已經(jīng)知道滑動(dòng)窗口中的窗口大小并不是越大越好,因?yàn)槿绻翱谌绻?,即傳輸大量的?shù)據(jù),此時(shí)接收方可能無(wú)法對(duì)這些數(shù)據(jù)進(jìn)行處理,同時(shí)也可能導(dǎo)致數(shù)據(jù)傳輸?shù)闹虚g鏈路也無(wú)法對(duì)這些數(shù)據(jù)進(jìn)行處理,進(jìn)而導(dǎo)致丟包問(wèn)題,此時(shí)我們就需要對(duì)這些丟失的數(shù)據(jù)進(jìn)行重傳。窗口太大的話并沒(méi)有提高傳輸數(shù)據(jù)的效率反而會(huì)降低數(shù)據(jù)傳輸?shù)男省?strong>流量控制就是針對(duì)窗口太大導(dǎo)致接收方無(wú)法處理大量數(shù)據(jù)的一種策略。
發(fā)送方發(fā)送數(shù)據(jù)接收方對(duì)數(shù)據(jù)進(jìn)行處理,這其實(shí)是一個(gè)生產(chǎn)者消費(fèi)者模型,如下圖:
現(xiàn)在來(lái)解釋什么是流量控制:流量控制就是根據(jù)接收方處理數(shù)據(jù)的能力來(lái)先至發(fā)送方窗口的大小。
那如何來(lái)衡量接收方處理數(shù)據(jù)的能力呢:可以通過(guò)接收方的接收緩沖區(qū)的剩余空間大小來(lái)衡量接收方處理數(shù)據(jù)的能力。如果剩余空間越大則說(shuō)明應(yīng)用程序處理數(shù)據(jù)的速度就越快。所以干脆我們直接把接收緩沖區(qū)剩余空間大小通過(guò)ACK報(bào)文反饋給發(fā)送方來(lái)作為發(fā)送方下一次發(fā)送數(shù)據(jù)、窗口大小的依據(jù)
。
TCP報(bào)文結(jié)構(gòu)中的16為窗口大小就是專門針對(duì)ACK報(bào)文而設(shè)定的,16位窗口大小就表示當(dāng)前接收方緩沖區(qū)剩余容量的大小,把這個(gè)數(shù)字作為ACK報(bào)文之后反饋給發(fā)送方來(lái)作為發(fā)送方下一次發(fā)送數(shù)據(jù)大小的依據(jù)。TCP中的16位窗口大小字段的取值范圍是0-65535,其中0表示接收方暫時(shí)不能接收數(shù)據(jù),1-65535表示接收方可以接收的數(shù)據(jù)大小,每個(gè)單位代表一個(gè)字節(jié)。在TCP的標(biāo)準(zhǔn)實(shí)現(xiàn)中,默認(rèn)窗口大小為64KB
(即65535個(gè)字節(jié))。但是這并不意味著16位窗口大小最大就是64kb。因?yàn)門CP報(bào)文選項(xiàng)中有一個(gè)選項(xiàng)窗口大小拓展因子。實(shí)際的16位窗口大小是16位窗口大小<<拓展因子
,此時(shí)能夠表示的窗口大小就非常大了。
下圖是流量控制具體的工作過(guò)程,請(qǐng)看:
此時(shí)主機(jī)A雖然不會(huì)發(fā)送數(shù)據(jù),但是由于主機(jī)A不知道主機(jī)B的接收緩沖區(qū)什么時(shí)候可以騰出空閑空間,所以主機(jī)A會(huì)周期性的向主機(jī)B發(fā)送窗口探測(cè)來(lái)觸發(fā)ACK以獲得主機(jī)B接收緩沖區(qū)的具體情況。
一旦發(fā)現(xiàn)主機(jī)B的接收緩沖區(qū)中有空閑內(nèi)存后,主機(jī)A就會(huì)繼續(xù)向主機(jī)B發(fā)送新的數(shù)據(jù)。
綜上,流量控制簡(jiǎn)單來(lái)說(shuō)就是接收方可以根據(jù)發(fā)送方窗口大小來(lái)反向限制發(fā)送方傳輸數(shù)據(jù)的速度。
??三、滑動(dòng)窗口——擁塞控制
主機(jī)A向主機(jī)B發(fā)送數(shù)據(jù)的過(guò)程中,中間會(huì)經(jīng)過(guò)一系列的交換機(jī)和路由器,所以數(shù)據(jù)傳輸?shù)男什粌H僅取決于主機(jī)A、主機(jī)B,還取決于中間鏈路傳輸數(shù)據(jù)的速度。如果中間鏈路的某個(gè)環(huán)節(jié)傳輸數(shù)據(jù)的速度很慢,此時(shí)發(fā)送方即主機(jī)A的發(fā)送數(shù)據(jù)的速度不應(yīng)該超過(guò)給環(huán)節(jié)傳輸數(shù)據(jù)的閾值。
那我們應(yīng)該如何衡量鏈路中間某個(gè)環(huán)節(jié)轉(zhuǎn)發(fā)數(shù)據(jù)的能力呢?
我們對(duì)中間鏈路環(huán)節(jié)的轉(zhuǎn)發(fā)能力并沒(méi)有很好的方式去進(jìn)行量化,所以只能通過(guò)實(shí)踐的方式來(lái)衡量中間鏈路環(huán)節(jié)的轉(zhuǎn)發(fā)能力:
使用一個(gè)較小的窗口進(jìn)行傳輸,如果傳輸通暢的話就將窗口調(diào)大
。使用一個(gè)較大的窗口進(jìn)行傳輸,如果傳輸異常的話就將窗口調(diào)小
。
簡(jiǎn)單來(lái)說(shuō)就是通暢調(diào)大,異常調(diào)小。
下面我們來(lái)看TCP中擁塞控制是如何進(jìn)行展開(kāi)的:
第一步:
慢啟動(dòng)
剛開(kāi)始進(jìn)行通信的時(shí)候先使用一個(gè)很小的窗口試試水。為什么一上來(lái)不使用很大的窗口呢,因?yàn)槿绻龅骄W(wǎng)絡(luò)擁堵的話,剛剛進(jìn)行網(wǎng)絡(luò)通信時(shí)使用較大的窗口(意味著數(shù)據(jù)量的龐大)就會(huì)給網(wǎng)絡(luò)帶寬帶來(lái)極大的負(fù)擔(dān)。
第二步:指數(shù)增長(zhǎng)
這里補(bǔ)充一個(gè)概念,即擁塞窗口:在擁塞窗口機(jī)制下使用的窗口大小。TCP發(fā)送方根據(jù)擁塞窗口的大小,確定可以發(fā)送的數(shù)據(jù)量。
指數(shù)增長(zhǎng)就是在網(wǎng)絡(luò)通暢的過(guò)程中,擁塞窗口的大小呈指數(shù)級(jí)別(*2)的增長(zhǎng)(由于指數(shù)增長(zhǎng)速度極快,所以對(duì)這里做出了一定的限制,請(qǐng)看第三步)。
第三步:線性增長(zhǎng)
指數(shù)增長(zhǎng)下當(dāng)擁塞窗口大小達(dá)到一個(gè)閾值后就會(huì)從指數(shù)增長(zhǎng)轉(zhuǎn)換為線性增長(zhǎng)(+n)。注意這里的指數(shù)增長(zhǎng)和線性增長(zhǎng)是根據(jù)數(shù)據(jù)傳輸?shù)妮喆蝸?lái)進(jìn)行的。比如說(shuō),現(xiàn)在給定窗口大小是1000,那么傳輸了1000數(shù)據(jù)之后,本輪數(shù)據(jù)的傳輸就結(jié)束了,當(dāng)接收方接收到ACK之后,繼續(xù)發(fā)送數(shù)據(jù)就進(jìn)入到了下一輪數(shù)據(jù)的傳輸,此時(shí)窗口大小就發(fā)生了變化,究竟是*2
還是+n
要根據(jù)具體情況具體分析。當(dāng)線性增長(zhǎng)增長(zhǎng)到一定程度之后,發(fā)送方發(fā)送數(shù)據(jù)的速度就會(huì)非常快,當(dāng)快的網(wǎng)絡(luò)的極限的時(shí)候就可能出現(xiàn)丟包
。
第四步:擁塞窗口回歸小窗口
當(dāng)窗口大小在增長(zhǎng)過(guò)程中如果出現(xiàn)丟包則認(rèn)為網(wǎng)絡(luò)出現(xiàn)擁堵了,此時(shí)就會(huì)把窗口大小調(diào)整到小窗口(即最開(kāi)始的慢窗口),繼續(xù)回到指數(shù)增長(zhǎng)和線性增長(zhǎng)的過(guò)程。當(dāng)然此時(shí)也會(huì)根據(jù)出現(xiàn)丟包的擁塞窗口的大小來(lái)調(diào)整閾值(這個(gè)閾值指的是指數(shù)增長(zhǎng)到線程增長(zhǎng)的閾值)。
下面是擁塞過(guò)程的詳細(xì)展開(kāi)圖:
綜上,擁塞控制即擁塞窗口的大小不斷發(fā)送變化調(diào)整從而適應(yīng)復(fù)雜多變的網(wǎng)絡(luò)環(huán)境。當(dāng)然這樣做的一個(gè)弊端就是會(huì)帶來(lái)數(shù)據(jù)傳輸上性能的損失,比如每次丟包后會(huì)重新回到慢開(kāi)始使得數(shù)據(jù)傳輸會(huì)大打折扣。所以擁塞控制就出現(xiàn)了很多優(yōu)化的版本(盡可能地把小窗口的傳輸時(shí)間縮短)。還有一點(diǎn)就是我們關(guān)注的是擁塞控制的這樣一個(gè)策略而不是這里的參數(shù),因?yàn)閰?shù)都是可以進(jìn)行調(diào)整的。
??四、總結(jié)
發(fā)送方實(shí)際窗口=min(流量控制窗口,擁塞窗口):這是因?yàn)樵诰W(wǎng)絡(luò)中,發(fā)送方的發(fā)送速率應(yīng)該受到接收方的接收速率限制(由流量控制窗口確定),同時(shí)也應(yīng)該受到網(wǎng)絡(luò)的擁塞程度限制(由擁塞窗口確定)。換句話來(lái)說(shuō)我們不僅僅要考慮到接收方的處理能力,同時(shí)也要考慮到中間鏈路的處理能力
。
滑動(dòng)窗口在保證數(shù)據(jù)傳輸可靠性的前提下一定程度上提高了數(shù)據(jù)傳輸?shù)男?,同時(shí)擁塞控制和流量控制共同限制了滑動(dòng)窗口機(jī)制,我們也可以說(shuō)擁塞控制和流量控制也是保證TCP可靠性的一種機(jī)制。
本文到這里就結(jié)束了,希望友友們可以支持一下一鍵三連哈。嗯,就到這里吧,再見(jiàn)啦!??!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-819639.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-819639.html
到了這里,關(guān)于【計(jì)算機(jī)網(wǎng)絡(luò)】TCP原理 | 可靠性機(jī)制分析(三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!