1. 前言
TCP是具備流控和可靠連接能力的協(xié)議,為防止TCP發(fā)生擁塞或?yàn)樘岣邆鬏斝?,在網(wǎng)
絡(luò)發(fā)展早期就提出了一些相關(guān)的TCP流控和優(yōu)化算法,而且也被RFC2581規(guī)定是每個(gè)
TCP實(shí)現(xiàn)時(shí)要實(shí)現(xiàn)的。
本文中,為求方便把將“TCP分組段(segment)”都直接稱為“包”。
2. 慢啟動(dòng)(slow start)和擁塞避免(Congestion Avoidance)
慢啟動(dòng)和擁塞避免是屬于TCP發(fā)送方必須(MUST)要實(shí)現(xiàn)的,防止TCP發(fā)送方向網(wǎng)絡(luò)傳入大量的突發(fā)數(shù)據(jù)造成網(wǎng)絡(luò)阻塞。
先介紹幾個(gè)相關(guān)參數(shù),是在通信雙方中需要考慮但不在TCP包中體現(xiàn)的一些參數(shù):
擁塞窗口(congestion window,cwnd),是指發(fā)送方在接收到對(duì)方的ACK確認(rèn)前向允許網(wǎng)絡(luò)發(fā)送的數(shù)據(jù)量,數(shù)據(jù)發(fā)送后,擁塞窗口縮?。唤邮盏綄?duì)方的ACK后,擁塞窗口相應(yīng)增加,擁塞窗口越大,可發(fā)送的數(shù)據(jù)量越大。擁塞窗口初始值的RFC2581中被規(guī)定為不超過(guò)發(fā)送方MSS的兩倍,而且不能超過(guò)兩個(gè)TCP包,在RFC3390中更新了初始窗口大小的設(shè)置方法。
通告窗口(advertised window,rwnd),是指接收方所能接收的沒(méi)來(lái)得及發(fā)ACK確認(rèn)的數(shù)據(jù)量,接收方數(shù)據(jù)接收后,通告窗口縮?。话l(fā)送ACK后,通告窗口相應(yīng)擴(kuò)大。
慢啟動(dòng)閾值(slow start threshold, ssthresh),用來(lái)判斷是否要使用慢啟動(dòng)或擁塞避免算法來(lái)控制流量的一個(gè)參數(shù),也是隨通信過(guò)程不斷變化的。
當(dāng)cwnd < ssthresh時(shí),擁塞窗口值已經(jīng)比較小了,表示未經(jīng)確認(rèn)的數(shù)據(jù)量增大,需要啟動(dòng)慢啟動(dòng)算法;當(dāng)cwnd > ssthresh時(shí),可發(fā)送數(shù)據(jù)量大,需要啟動(dòng)擁塞避免算法。
擁塞窗口cwnd是根據(jù)發(fā)送的數(shù)據(jù)量自動(dòng)減小的,但擴(kuò)大就需要根據(jù)對(duì)方的接收情況進(jìn)行擴(kuò)大,慢啟動(dòng)和擁塞避免算法都是描述如何擴(kuò)大該值的。
在啟動(dòng)慢啟動(dòng)算法時(shí),TCP發(fā)送方接收到對(duì)方的ACK后擁塞窗口最多每次增加一個(gè)發(fā)送方MSS字節(jié)的數(shù)值,當(dāng)擁塞窗口超過(guò)sshresh后或觀察到擁塞才停止算法。
啟動(dòng)擁塞避免算法時(shí),擁塞窗口在一個(gè)連接往返時(shí)間RTT內(nèi)增加一個(gè)最大TCP包長(zhǎng)度的量,一般實(shí)現(xiàn)時(shí)用以下公式計(jì)算:
cwnd += max(SMSS*SMSS/cwnd, 1) (2.1)
SMSS為發(fā)送方MSS。
TCP發(fā)送方檢測(cè)到數(shù)據(jù)包丟失時(shí),需要調(diào)整ssthresh,一般按下面公式計(jì)算:
ssthresh = max (FlightSize / 2, 2*SMSS) (2.2)
其中FlightSize表示已經(jīng)發(fā)送但還沒(méi)有被確認(rèn)的數(shù)據(jù)量。
3. 快速重傳(fast retransmit)和快速恢復(fù)(fast recovery)
TCP接收方收到錯(cuò)序的TCP包時(shí)要發(fā)送復(fù)制的ACK包回應(yīng),提示發(fā)送方可能出現(xiàn)網(wǎng)絡(luò)丟包;發(fā)送方
收到連續(xù)3個(gè)重復(fù)的ACK包后啟動(dòng)快速重傳算法,根據(jù)確認(rèn)號(hào)快速重傳那個(gè)可能丟失的包而不必等
重傳定時(shí)器超時(shí)后再重傳,普通的重傳是要等到重傳定時(shí)器超時(shí)還沒(méi)收到ACK才進(jìn)行的。這個(gè)算
法是TCP發(fā)送方應(yīng)該(SHOULD)實(shí)現(xiàn)的,不是必須。TCP發(fā)送方進(jìn)行了快速重傳后進(jìn)入快速恢復(fù)階段
,直到?jīng)]再接收重復(fù)的ACK包。
快速重傳和快速恢復(fù)具體過(guò)程為:
1. 當(dāng)收到第3個(gè)重復(fù)的ACK包時(shí),ssthreh值按公式2.2重新設(shè)置;
2. 重傳丟失的包后,將擁塞窗口cwnd設(shè)置為sshresh+3*SMSS,人工擴(kuò)大了擁塞窗口;
3. 對(duì)于每個(gè)接收到的重復(fù)的ACK包,cwnd相應(yīng)增加SMSS,擴(kuò)大擁塞窗口;
4. 如果新的擁塞窗口cwnd值和接收方的通告窗口值允許的話,可以繼續(xù)發(fā)新包;
5. 當(dāng)收到下一個(gè)ACK確認(rèn)了新數(shù)據(jù)時(shí),將cwnd大小調(diào)整為sshresh,減少窗口;對(duì)接收方
來(lái)說(shuō),接收到重發(fā)的TCP包后就要發(fā)此ACK確認(rèn)當(dāng)前接收的數(shù)據(jù)。
4. 結(jié)論
這些算法重點(diǎn)在于保持網(wǎng)絡(luò)的可靠性和可用性,防止網(wǎng)絡(luò)阻塞造成的網(wǎng)絡(luò)崩潰,是相對(duì)
比較保守的。
5. 附錄討論
A君: 這些算法都是針對(duì)通信雙方的事, 但如果從開(kāi)發(fā)防火墻等中間設(shè)備的角度來(lái)看,
中間設(shè)備有必要考慮這些么?
端木: 這個(gè)...我好象也看不出必要性,因?yàn)樗惴ǖ膮?shù)都是在雙方內(nèi)部而不在TCP數(shù)據(jù)包
中體現(xiàn)...但應(yīng)該會(huì)讓中間設(shè)備輕松點(diǎn),這個(gè)就象在馬路開(kāi)車,這些算法就是交規(guī)
讓你開(kāi)得規(guī)矩點(diǎn),交警只關(guān)心你開(kāi)車的情況,而不管你開(kāi)的是什么車,開(kāi)得好交警
也輕松。好車可以讓你很容易開(kāi)好,但差車也可以開(kāi)好。
A君: 這些算法原型提出也很早了, 最早是88年的事, 當(dāng)時(shí)網(wǎng)絡(luò)都處于初級(jí)階段, 有個(gè)
9600bps的貓就很牛了, 計(jì)算機(jī)性能也很差, 因此實(shí)施這些算法還有點(diǎn)用; 但現(xiàn)
在過(guò)了快20年了, 百兆都快淘汰, 千兆, 萬(wàn)兆網(wǎng)絡(luò)都快普及了, 即使PC機(jī)的內(nèi)存
也都上G了,再規(guī)矩這種幾K級(jí)別的數(shù)據(jù)量有意思么? 就好象現(xiàn)在噴氣式戰(zhàn)斗機(jī)都到
第4代了, 再研究螺旋槳戰(zhàn)斗機(jī)還有意思么?
端木: 這個(gè)...這個(gè)就象病毒庫(kù)了, 里面不也有無(wú)數(shù)的DOS時(shí)代的病毒, 你以后這輩子估計(jì)
都見(jiàn)不著的,但沒(méi)有哪個(gè)防病毒廠商會(huì)把這些病毒從庫(kù)中剔除,庫(kù)是只增不減的。
有這么個(gè)東西也是一樣,正因?yàn)槠綍r(shí)沒(méi)用,誰(shuí)也不注意,知道了就可以吹一吹,
尤其拿去?;H耸呛苡行У?!
A君: 你真無(wú)聊!
端木: You got it! 不無(wú)聊干嗎寫(xiě)博客啊!
端木: 搞技術(shù)有時(shí)候是很悲哀的一件事,必須牽扯七大姑八大姨的很多老東西,也就是向下
兼容,到一定程度將成為進(jìn)一步發(fā)展的最大障礙,講一個(gè)從smth看到的不是笑話
的笑話:
現(xiàn)代鐵路的鐵軌間距是4英尺8點(diǎn)5英寸,鐵軌間距采用了電車輪距的標(biāo)準(zhǔn),而電車輪距
的標(biāo)準(zhǔn)則沿襲了馬車的輪距標(biāo)準(zhǔn)。
馬車的輪距為何是4英尺8點(diǎn)5英寸?原來(lái),英國(guó)的馬路轍跡的寬度是4英尺8點(diǎn)5英寸。
如果馬車改用其他尺寸的輪距,輪子很快就會(huì)在英國(guó)的老馬路上撞壞。
英國(guó)馬路的轍跡寬度又從何而來(lái)?這可以上溯到古羅馬時(shí)期。整個(gè)歐洲(包括英國(guó))的老路都是羅馬人為其軍隊(duì)鋪設(shè)的,4英尺8點(diǎn)5英寸正是羅馬戰(zhàn)車的寬度。
羅馬戰(zhàn)車的寬度又是怎么來(lái)的?答案很簡(jiǎn)單,它是牽引一輛戰(zhàn)車的兩匹馬的屁股的總寬度。
段子到這里還沒(méi)有結(jié)束。美國(guó)航天飛機(jī)的火箭助推器也擺脫不了馬屁股的糾纏———火箭助推器造好之后要經(jīng)過(guò)鐵路運(yùn)送,而鐵路上必然有一些隧道,隧道的寬度又是根據(jù)鐵軌的寬度而來(lái)。代表著尖端科技的火箭助推器的寬度,竟然被兩匹馬的屁股的總寬度決定了。
轉(zhuǎn)自:
http://www.shnenglu.com/prayer/archive/2009/04/20/80527.html
posted on 2010-01-08 23:34
chatler 閱讀(573)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
Network