第二十一章: TCP的超時(shí)與重傳

21.1 引言

TCP提供可靠的運(yùn)輸層渴丸。它使用的方法之一就是確認(rèn)從另一端收到的數(shù)據(jù)。但數(shù)據(jù)和確認(rèn)都有可能會(huì)丟失冶忱。TCP通過在發(fā)送時(shí)設(shè)置一個(gè)定時(shí)器來解決這種問題袱箱。如果當(dāng)定時(shí)器溢出時(shí)還沒有收到確認(rèn),它就重傳該數(shù)據(jù)式曲。對(duì)任何實(shí)現(xiàn)而言妨托,關(guān)鍵之處就在于超時(shí)和重傳的策略缸榛,即怎樣決定超時(shí)間隔和如何確定重傳的頻率。

我們已經(jīng)看到過兩個(gè)超時(shí)和重傳的例子:(1)在6.5節(jié)的ICMP端口不能到達(dá)的例子中兰伤,看到TFTP客戶使用UDP實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的超時(shí)和重傳機(jī)制:假定5秒是一個(gè)適當(dāng)?shù)臅r(shí)間間隔内颗,并每隔5秒進(jìn)行重傳;(2)在向一個(gè)不存在的主機(jī)發(fā)送ARP的例子中(第4.5節(jié))敦腔,我們看到當(dāng)TCP試圖建立連接的時(shí)候均澳,在每個(gè)重傳之間使用一個(gè)較長(zhǎng)的時(shí)延來重傳SYN。

對(duì)每個(gè)連接符衔,TCP管理4個(gè)不同的定時(shí)器找前。

1:重傳定時(shí)器使用于當(dāng)希望收到另一端的確認(rèn)。在本章我們將詳細(xì)討論這個(gè)定時(shí)器以及一些相關(guān)的問題判族,如擁塞避免躺盛。

2:堅(jiān)持(persist)定時(shí)器使窗口大小信息保持不斷流動(dòng),即使另一端關(guān)閉了其接收窗口形帮。第22章將討論這個(gè)問題槽惫。

3:保活(keepalive)定時(shí)器可檢測(cè)到一個(gè)空閑連接的另一端何時(shí)崩潰或重啟辩撑。第23章將描述這個(gè)定時(shí)器界斜。

4:2MSL定時(shí)器測(cè)量一個(gè)連接處于TIME_WA IT狀態(tài)的時(shí)間。我們?cè)?8.6節(jié)對(duì)該狀態(tài)進(jìn)行了介紹槐臀。

本章以一個(gè)簡(jiǎn)單的TCP超時(shí)和重傳的例子開始锄蹂,然后轉(zhuǎn)向一個(gè)更復(fù)雜的例子。該例子可以使我們觀察到TCP時(shí)鐘管理的所有細(xì)節(jié)水慨〉妹樱可以看到TCP的典型實(shí)現(xiàn)是怎樣測(cè)量TCP報(bào)文段的往返時(shí)間以及TCP如何使用這些測(cè)量結(jié)果來為下一個(gè)將要傳輸?shù)膱?bào)文段建立重傳超時(shí)時(shí)間。接著我們將研究TCP的擁塞避免—當(dāng)分組丟失時(shí)TCP所采取的動(dòng)作—并提供一個(gè)分組丟失的實(shí)際例子晰洒,我們還將介紹較新的快速重傳和快速恢復(fù)算法朝抖,并介紹該算法如何使TCP檢測(cè)分組丟失比等待時(shí)鐘超時(shí)更快。

21.2 超時(shí)與重傳的簡(jiǎn)單例子

首先觀察TCP所使用的重傳機(jī)制谍珊,我們將建立一個(gè)連接治宣,發(fā)送一些分組來證明一切正常,然后拔掉電纜砌滞,發(fā)送更多的數(shù)據(jù)侮邀,再觀察TCP的行為。

圖21-1表示的是tcpdump的輸出結(jié)果(已經(jīng)去掉了bsdi設(shè)置的服務(wù)類型信息)贝润。

圖21-1 TCP超時(shí)和重傳的簡(jiǎn)單例子

第1绊茧、2和3行表示正常的TCP連接建立的過程,第4行是“hello,world”(12個(gè)字符加上回車和換行)的傳輸過程打掘,第5行是其確認(rèn)华畏。接著我們從svr4拔掉了以太網(wǎng)電纜鹏秋,第6行表示“and hi”將被發(fā)送。第7~18行是這個(gè)報(bào)文段的12次重傳過程亡笑,而第19行則是發(fā)送方的TCP最終放棄并發(fā)送一個(gè)復(fù)位信號(hào)的過程侣夷。

現(xiàn)在檢查連續(xù)重傳之間不同的時(shí)間差,它們?nèi)≌蠓謩e為1仑乌、3百拓、6、12绝骚、24耐版、48和多個(gè)64秒祠够。在本章的后面压汪,我們將看到當(dāng)?shù)谝淮伟l(fā)送后所設(shè)置的超時(shí)時(shí)間實(shí)際上為1.5秒(它在首次發(fā)送后的1.0136秒而不是精確的1.5秒后,發(fā)生的原因我們已在圖18-7中進(jìn)行了解釋)古瓤,此后該時(shí)間在每次重傳時(shí)增加1倍并直至64秒止剖。

這個(gè)倍乘關(guān)系被稱為“指數(shù)退避(exponential backoff)”÷渚可以將該例子與6.5節(jié)中的TFTP例子比較穿香,在那里每次重傳總是在前一次的5秒后發(fā)生。

首次分組傳輸(第6行绎速,24.480秒)與復(fù)位信號(hào)傳輸(第19行皮获,566.488秒)之間的時(shí)間差約為9分鐘,該時(shí)間在目前的TCP實(shí)現(xiàn)中是不可變的纹冤。

對(duì)于大多數(shù)實(shí)現(xiàn)而言洒宝,這個(gè)總時(shí)間是不可調(diào)整的。Solaris 2.2允許管理者改變這個(gè)時(shí)間(E.4節(jié)中的tcp_ip_abort_interval變量)萌京,且其默認(rèn)值為2分鐘雁歌,而不是最常用的9分鐘。

21.3 往返時(shí)間測(cè)量

TCP超時(shí)與重傳中最重要的部分就是對(duì)一個(gè)給定連接的往返時(shí)間(RTT)的測(cè)量知残。由于路由器和網(wǎng)絡(luò)流量均會(huì)變化靠瞎,因此我們認(rèn)為這個(gè)時(shí)間可能經(jīng)常會(huì)發(fā)生變化,TCP應(yīng)該跟蹤這些變化并相應(yīng)地改變其超時(shí)時(shí)間求妹。

首先TCP必須測(cè)量在發(fā)送一個(gè)帶有特別序號(hào)的字節(jié)和接收到包含該字節(jié)的確認(rèn)之間的RTT乏盐。在上一章中,我們?cè)岬皆跀?shù)據(jù)報(bào)文段和ACK之間通常并沒有一一對(duì)應(yīng)的關(guān)系制恍。在圖20.1中父能,這意味著發(fā)送方可以測(cè)量到的一個(gè)RT T,是在發(fā)送報(bào)文段4(第11024字節(jié))和接收?qǐng)?bào)文段7(對(duì)11024字節(jié)的ACK)之間的時(shí)間吧趣,用M表示所測(cè)量到的RTT法竞。

最初的TCP規(guī)范使TCP使用低通過濾器來更新一個(gè)被平滑的RT T估計(jì)器(記為O)耙厚。

這里的α是一個(gè)推薦值為0.9的平滑因子。每次進(jìn)行新測(cè)量的時(shí)候岔霸,這個(gè)被平滑的RTT將得到更新薛躬。每個(gè)新估計(jì)的90%來自前一個(gè)估計(jì),而10%則取自新的測(cè)量呆细。

該算法在給定這個(gè)隨RT T的變化而變化的平滑因子的條件下型宝,RFC 793推薦的重傳超時(shí)時(shí)間RTO(Retransmission TimeOut)的值應(yīng)該設(shè)置為

這里的β是一個(gè)推薦值為2的時(shí)延離散因子。

[Jacobson 1988]詳細(xì)分析了在RTT變化范圍很大時(shí)絮爷,使用這個(gè)方法無法跟上這種變化趴酣,從而引起不必要的重傳。正如Jacobson記述的那樣坑夯,當(dāng)網(wǎng)絡(luò)已經(jīng)處于飽和狀態(tài)時(shí)岖寞,不必要的重傳會(huì)增加網(wǎng)絡(luò)的負(fù)載,對(duì)網(wǎng)絡(luò)而言這就像在火上澆油一樣柜蜈。

除了被平滑的RTT估計(jì)器仗谆,所需要做的還有跟蹤RT T的方差。在往返時(shí)間變化起伏很大時(shí)淑履,基于均值和方差來計(jì)算RTO隶垮,將比作為均值的常數(shù)倍數(shù)來計(jì)算RTO能提供更好的響應(yīng)。在[Jacobson 1988] 中的圖5和圖6中顯示了根據(jù)RFC 793計(jì)算的某些實(shí)際往返時(shí)間的RTO和下面考慮了往返時(shí)間的方差所計(jì)算的RTO的比較結(jié)果秘噪。

正如Jacobson所描述的狸吞,均值偏差是對(duì)標(biāo)準(zhǔn)偏差的一種好的逼近,但卻更容易進(jìn)行計(jì)算(計(jì)算標(biāo)準(zhǔn)偏差需要一個(gè)平方根)指煎。這就引出了下面用于每個(gè)RTT測(cè)量M的公式蹋偏。



這里的A是被平滑的RTT(均值的估計(jì)器)而D則是被平滑的均值偏差。Err是剛得到的測(cè)量結(jié)果與當(dāng)前的RTT估計(jì)器之差贯要。A和D均被用于計(jì)算下一個(gè)重傳時(shí)間(RTO)暖侨。增量g起平均作用,取為1/8(0.125)崇渗。偏差的增益是h字逗,取值為0.25。當(dāng)RTT變化時(shí)宅广,較大的偏差增益將使RTO快速上升葫掉。

[Jacobson 1988]指明在計(jì)算RTO時(shí)使用2D,但經(jīng)過后來更深入的研究跟狱,[Jacobson1990c]將該值改為4D俭厚,也就是在BSD Net/1的實(shí)現(xiàn)中使用的那樣。

Jacobson指明了一種使用整數(shù)運(yùn)算來計(jì)算這些公式的方法驶臊,并被許多實(shí)現(xiàn)所采用(這也就是g挪挤,h和倍數(shù)4均是2的乘方的一個(gè)原因叼丑,這樣一來計(jì)算均可只通過移位操作而不需要乘、除運(yùn)算來完成)扛门。

將Jacobson與最初的方法比較鸠信,我們發(fā)現(xiàn)被平滑的均值計(jì)算公式是類似的(α是1減去增益g),而增益可使用不同的值论寨。而且Jacobson計(jì)算RTO的公式依賴于被平滑的RT T和被平滑的均值偏差星立,而最初的方法則使用了被平滑的RT T的一個(gè)倍數(shù)。

在看完下一節(jié)中的例子時(shí)葬凳,我們將看到這些估計(jì)器是如何被初始化的绰垂。

Karn算法

在一個(gè)分組重傳時(shí)會(huì)產(chǎn)生這樣一個(gè)問題:假定一個(gè)分組被發(fā)送。當(dāng)超時(shí)發(fā)生時(shí)火焰,RTO正如21.2節(jié)中顯示的那樣進(jìn)行退避劲装,分組以更長(zhǎng)的RTO進(jìn)行重傳,然后收到一個(gè)確認(rèn)荐健。那么這個(gè)ACK是針對(duì)第一個(gè)分組的還是針對(duì)第二個(gè)分組呢酱畅?這就是所謂的重傳多義性問題。

[Karn and Partridge 1987]規(guī)定江场,當(dāng)一個(gè)超時(shí)和重傳發(fā)生時(shí),在重傳數(shù)據(jù)的確認(rèn)最后到達(dá)之前窖逗,不能更新RT T估計(jì)器址否,因?yàn)槲覀儾⒉恢繟CK對(duì)應(yīng)哪次傳輸(也許第一次傳輸被延遲而并沒有被丟棄,也有可能第一次傳輸?shù)腁CK被延遲)碎紊。

并且佑附,由于數(shù)據(jù)被重傳,RTO已經(jīng)得到了一個(gè)指數(shù)退避仗考,我們?cè)谙乱淮蝹鬏敃r(shí)使用這個(gè)退避后的RTO音同。對(duì)一個(gè)沒有被重傳的報(bào)文段而言,除非收到了一個(gè)確認(rèn)秃嗜,否則不要計(jì)算新的RTO权均。

21.4 往返時(shí)間RTT的例子

在本章中,我們將使用以下這些例子來檢查TCP的超時(shí)和重傳锅锨、慢啟動(dòng)以及擁塞避免等方方面面的實(shí)現(xiàn)細(xì)節(jié)叽赊。

使用sock程序和如下的命令來將32768字節(jié)的數(shù)據(jù)從主機(jī)slip發(fā)送到主機(jī)vangogh.cs.berkeley.edu上的丟棄服務(wù)。

slip % sock -D -i -n32 vangogh.cs.berkeley.edu discard

在扉頁(yè)前圖中必搞,可以看到slip通過兩個(gè)SLIP鏈路與140.252.1以太網(wǎng)相連必指,并從這里通過Internet到達(dá)目的地。通過使用兩個(gè)9600 b/s的SLIP鏈路恕洲,我們期望能夠得到一些可測(cè)量的時(shí)延塔橡。

該命令執(zhí)行32個(gè)寫1024字節(jié)的操作梅割。由于slip和bsdi之間的MTU為296字節(jié),因此這些操作會(huì)產(chǎn)生128個(gè)報(bào)文段葛家,每個(gè)報(bào)文段包含256字節(jié)的用戶數(shù)據(jù)炮捧。整個(gè)傳輸過程的時(shí)間約為45秒,我們觀察到了一個(gè)超時(shí)和三次重傳惦银。

當(dāng)該傳輸過程進(jìn)行時(shí)咆课,我們?cè)趕lip上使用tcpdump來截獲所有的發(fā)送和接收的報(bào)文段,并通過使用-D選項(xiàng)來打開插口排錯(cuò)功能(見A.6節(jié))扯俱,這樣便可以通過運(yùn)行一個(gè)修改后的trpt(8)程序來打印出連接控制塊中與RTT书蚪、慢啟動(dòng)及擁塞避免等有關(guān)的多個(gè)變量。

對(duì)于給出的跟蹤結(jié)果迅栅,我們不能夠完全進(jìn)行顯示殊校,相反,我們將在介紹本章時(shí)看到它的各個(gè)部分。圖21-2顯示的是前5秒中的數(shù)據(jù)和確認(rèn)的傳輸過程。與前面tcpdump的輸出相比艰争,我們已對(duì)其顯示稍微進(jìn)行了修改莉撇。雖然我們僅能夠在運(yùn)行tcpdump的主機(jī)上測(cè)量分組發(fā)送和接收的時(shí)間,但在本圖中我們希望顯示出分組正在網(wǎng)絡(luò)中傳輸(它們確實(shí)存在舒萎,因?yàn)檫@個(gè)局域網(wǎng)連接與共享式的以太網(wǎng)并不一樣)以及接收主機(jī)何時(shí)可能產(chǎn)生ACK(在本圖中去掉了所有的窗口大小通告。主機(jī)slip總是通告窗口大小為4096,而vangogh則總是通告窗口大小為8192)莲祸。

還需要注意的是在本圖中我們已經(jīng)將報(bào)文段按照在主機(jī)slip上發(fā)送和接收的序號(hào)記為1~13和15。這與在這個(gè)主機(jī)上所收集的tcpdump的輸出結(jié)果有關(guān)椭迎。

21.4.1 往返時(shí)間RTT的測(cè)量

在圖21-2左邊的時(shí)間軸上有三個(gè)括號(hào)锐帜,它們表明為進(jìn)行RTT計(jì)算對(duì)哪些報(bào)文段進(jìn)行了計(jì)時(shí),并不是所有的報(bào)文段都被計(jì)時(shí)畜号。

大多數(shù)源于伯克利的TCP實(shí)現(xiàn)在任何時(shí)候?qū)γ總€(gè)連接僅測(cè)量一次RTT值缴阎。在發(fā)送一個(gè)報(bào)文段時(shí),如果給定連接的定時(shí)器已經(jīng)被使用简软,則該報(bào)文段不被計(jì)時(shí)蛮拔。

圖21-2 分組交換和RTT測(cè)量

在每次調(diào)用500 ms的TCP的定時(shí)器例程時(shí),就增加一個(gè)計(jì)數(shù)器來完成計(jì)時(shí)替饿。這意味著语泽,如果一個(gè)報(bào)文段的確認(rèn)在它發(fā)送550 ms后到達(dá),則該報(bào)文段的往返時(shí)間RT T將是1個(gè)滴答(即500 ms)或是2個(gè)滴答(即1000 ms)视卢。

對(duì)每個(gè)連接而言踱卵,除了這個(gè)滴答計(jì)數(shù)器,報(bào)文段中數(shù)據(jù)的起始序號(hào)也被記錄下來。當(dāng)收到一個(gè)包含這個(gè)序號(hào)的確認(rèn)后惋砂,該定時(shí)器就被關(guān)閉妒挎。如果ACK到達(dá)時(shí)數(shù)據(jù)沒有被重傳,則被平滑的RTT和被平滑的均值偏差將基于這個(gè)新測(cè)量進(jìn)行更新西饵。

圖21-2中連接上的定時(shí)器在發(fā)送報(bào)文段1時(shí)啟動(dòng)酝掩,并在確認(rèn)(報(bào)文段2)到達(dá)時(shí)終止。盡管它的RTT是1.061秒(tcpdump的輸出)眷柔,但插口排錯(cuò)的信息顯示該過程經(jīng)歷了3個(gè)TCP時(shí)鐘滴答期虾,即RTT為1500 ms。

下一個(gè)被計(jì)時(shí)的是報(bào)文段3驯嘱。當(dāng)2.4ms后傳輸報(bào)文段4時(shí)镶苞,由于連接的定時(shí)器已經(jīng)被啟動(dòng),因此該報(bào)文段不能被計(jì)時(shí)鞠评。當(dāng)報(bào)文段5到達(dá)時(shí)茂蚓,確認(rèn)了正在被計(jì)時(shí)的數(shù)據(jù)。雖然我們從tcpdump的輸出結(jié)果可以看到其RTT是0.808秒剃幌,但它的RTT被計(jì)算為1個(gè)滴答(500 ms)聋涨。

定時(shí)器在發(fā)送報(bào)文段6時(shí)再次被啟動(dòng),并在1.015秒后接收到它的確認(rèn)(報(bào)文段10)時(shí)終止负乡。測(cè)量到的RTT是2個(gè)滴答牍白。報(bào)文段7和9不能被計(jì)時(shí),因?yàn)槎〞r(shí)器已經(jīng)被使用敬鬓。而且淹朋,當(dāng)收到報(bào)文段8(第769字節(jié)的確認(rèn))時(shí),由于該報(bào)文段不是正在計(jì)時(shí)的數(shù)據(jù)的確認(rèn)钉答,因此什么也沒有進(jìn)行更新。

圖21-3顯示了本例中通過tcpdump的輸出所得到的實(shí)際RTT與時(shí)鐘滴答計(jì)數(shù)之間的關(guān)系杈抢。

圖21-3 RTT測(cè)量和時(shí)鐘滴答

在圖的上端表示間隔為500 ms的時(shí)鐘滴答数尿,圖的下端表示tcpdump的輸出時(shí)間及定時(shí)器何時(shí)被啟動(dòng)和關(guān)閉。在發(fā)送報(bào)文段1和接收到報(bào)文段2之間經(jīng)歷了3個(gè)滴答惶楼,時(shí)間為1.061秒右蹦,因此假定第1個(gè)滴答發(fā)生在0.03秒處(第1個(gè)滴答一定在0~0.061秒之間)。接著該圖表示了第2個(gè)被測(cè)量的RTT為什么被記為1個(gè)滴答歼捐,而第3個(gè)被記為2個(gè)滴答何陆。

在這個(gè)完整的例子中,128個(gè)報(bào)文段被傳送豹储,并收集了18個(gè)RTT采樣贷盲。圖21-4表示了測(cè)量的RTT(取自tcpdump的輸出)和TCP為超時(shí)所使用的RTO(取自插口排錯(cuò)的輸出)。在圖21-2中,x軸從時(shí)間0開始巩剖,表示的是傳輸報(bào)文段1的時(shí)刻铝穷,而不是傳輸?shù)?個(gè)SYN的時(shí)刻。

圖21-4 測(cè)量出的RTT和TCP計(jì)算的RTO的例子

測(cè)量出RTT的前3個(gè)數(shù)據(jù)點(diǎn)對(duì)應(yīng)圖21-2所示的3個(gè)RTT佳魔。在時(shí)間10,14和21處的間隔是由在這些時(shí)刻附近發(fā)生的重傳(將在本章后面給出)引起的曙聂。Karn算法在另一個(gè)報(bào)文段被發(fā)送和確認(rèn)之前阻止我們更新估計(jì)器。同樣注意到在這個(gè)實(shí)現(xiàn)中鞠鲜,TCP計(jì)算的RTO總是500 ms的倍數(shù)宁脊。

21.4.2 RTT估計(jì)器的計(jì)算

讓我們來看一下RTT估計(jì)器(平滑的RT T和平滑的均值偏差)是如何被初始化和更新,以及每個(gè)重傳超時(shí)是怎樣計(jì)算的贤姆。

變量A和D分別被初始化為0和3秒榆苞。初始的重傳超時(shí)使用下面的公式進(jìn)行計(jì)算

(因子2D只在這個(gè)初始化計(jì)算中使用。正如前面提到的庐氮,以后使用4D和A相加來計(jì)算RTO)语稠。這就是傳輸初始SYN所使用的RTO。

結(jié)果是這個(gè)初始SYN丟失了弄砍,然后超時(shí)并引起了重傳仙畦。圖21-5給出了tcpdump輸出文件中的前4行。

圖21-5 初始SYN的超時(shí)和重傳

當(dāng)超時(shí)在5.802秒后發(fā)生時(shí)音婶,計(jì)算當(dāng)前的RTO值為

RTO = A + 4D = 0 + 4 × 3 = 12s

因此慨畸,應(yīng)用于RTO的指數(shù)退避取為12。由于這是第1次超時(shí)衣式,我們使用倍數(shù)2寸士,因此下一個(gè)超時(shí)時(shí)間取值為24秒。再下一個(gè)超時(shí)時(shí)間的倍數(shù)為4碴卧,得出值為48秒(這些初始RTO弱卡,對(duì)于一個(gè)連接上的最初的SYN,取值為6秒住册,接下來為24秒婶博,正是我們?cè)趫D4-5中看到的)。

ACK在重傳后467ms到達(dá)荧飞。A和D的值沒有被更新凡人,這是因?yàn)镵arn算法對(duì)重傳的處理比較模糊。下一個(gè)發(fā)送的報(bào)文段是第4行的ACK叹阔,但它只是一個(gè)ACK挠轴,所以沒有被計(jì)時(shí)(只有數(shù)據(jù)報(bào)文段才會(huì)被計(jì)時(shí))。

當(dāng)發(fā)送第1個(gè)數(shù)據(jù)報(bào)文段時(shí)(圖21-2中的報(bào)文段1)耳幢,RTO沒有改變岸晦,這同樣是由于Karn算法。當(dāng)前的24秒一直被使用,直到進(jìn)行一個(gè)RTT測(cè)量委煤。這意味著圖21-4中時(shí)間0的RTO并不真的是24堂油,但我們沒有畫出那個(gè)點(diǎn)。

當(dāng)?shù)?個(gè)數(shù)據(jù)報(bào)文段的ACK(圖21-2中的報(bào)文段2)到達(dá)時(shí)碧绞,經(jīng)歷了3個(gè)時(shí)鐘滴答府框,估計(jì)器被初始化為


(因?yàn)榻?jīng)歷3個(gè)時(shí)鐘滴答,因此讥邻,M取值為1.5)迫靖。在前面,A和D初始化為0兴使,RTO的初始計(jì)算值為3系宜。這是使用第1個(gè)RTT的測(cè)量結(jié)果M對(duì)估計(jì)器進(jìn)行首次計(jì)算的初始值。計(jì)算的RTO值為



當(dāng)?shù)?個(gè)數(shù)據(jù)報(bào)文段的ACK(圖21-2中的報(bào)文段5)到達(dá)時(shí)发魄,經(jīng)歷了1個(gè)時(shí)鐘滴答(0.5秒)盹牧,估計(jì)器按如下更新:

Err、A和D的定點(diǎn)表示與實(shí)際使用的定點(diǎn)計(jì)算(在簡(jiǎn)化浮點(diǎn)計(jì)算中表示過)有一些微小的差別励幼。這些不同使RTO取值為6秒(而非6.3125秒)汰寓,正如我們?cè)趫D21-4中的時(shí)間1.871處所畫的那樣。

21.4.3 慢啟動(dòng)

我們?cè)诘?0.6節(jié)介紹了慢啟動(dòng)算法苹粟,在圖21-2中可再次看到它的工作過程有滑。

連接上最初只允許傳輸一個(gè)報(bào)文段,然后在發(fā)送下一個(gè)報(bào)文段之前必須等待接收它的確認(rèn)嵌削。當(dāng)報(bào)文段2被接收后毛好,就可以再發(fā)送兩個(gè)報(bào)文段。

21.5 擁塞舉例

現(xiàn)在觀察一下數(shù)據(jù)報(bào)文段的傳輸過程苛秕。圖21-6顯示了報(bào)文段中數(shù)據(jù)的起始序號(hào)與該報(bào)文段發(fā)送時(shí)間的對(duì)比圖肌访。它提供了一種較好的數(shù)據(jù)傳輸?shù)目梢暬椒āMǔ4頂?shù)據(jù)的點(diǎn)將向上和向右移動(dòng)艇劫,這些點(diǎn)的斜率就表示傳輸速率场靴。當(dāng)這些點(diǎn)向下和向右移動(dòng)則表示發(fā)生了重傳。

在21.4節(jié)開始時(shí)港准,我們?cè)岬秸麄€(gè)傳輸?shù)臅r(shí)間約為45秒,但在本圖中只顯示了35秒鐘咧欣。這35秒只是數(shù)據(jù)報(bào)文段發(fā)送的時(shí)間浅缸。因?yàn)榈?個(gè)SYN看來是丟失了并被重傳(見圖21-5),因此第1個(gè)數(shù)據(jù)報(bào)文段是在第1個(gè)SYN發(fā)送6.3秒后才發(fā)送的魄咕。而且衩椒,在發(fā)送最后一個(gè)數(shù)據(jù)報(bào)文段和FIN(圖21-6中的34.1秒)之后,在接收方的FIN到達(dá)之前,又花費(fèi)了另外的4.0秒接收來自接收方的最后14個(gè)ACK毛萌。

圖21-6 從slip發(fā)送32768個(gè)字節(jié)的數(shù)據(jù)到vangogh

可以立即看到圖21-6中發(fā)生在時(shí)刻10苟弛,14和21附近的3個(gè)重傳。我們還可以看到在這3個(gè)點(diǎn)中只進(jìn)行了一次報(bào)文段的重傳阁将,因?yàn)橹挥幸粋€(gè)點(diǎn)下垂低于向上的斜率膏秫。

仔細(xì)檢查一下這幾個(gè)下垂點(diǎn)中的第1個(gè)點(diǎn)(在10秒標(biāo)記處的附近)。整理tcpdump的輸出結(jié)果可以得到圖21-7做盅。

在這個(gè)圖中缤削,除了下面將要討論的報(bào)文段72,已經(jīng)去掉了其他所有的窗口通告吹榴。主機(jī)slip總是通告窗口大小為4096亭敢,而主機(jī)vangogh則通告窗口為8192。該圖中報(bào)文段的編號(hào)可以看作是圖21-2的延續(xù)图筹,在那里報(bào)文段的編號(hào)從1開始帅刀。與圖21-2一樣,報(bào)文段根據(jù)在slip上發(fā)送和接收的順序進(jìn)行編號(hào)远剩,tcpdump在主機(jī)slip上運(yùn)行扣溺。我們還去掉了一些與討論無關(guān)的段(第44,47和49以及所有來自vangogh的ACK)。

圖21-7 10秒標(biāo)記處附近重傳的分組交換

看來報(bào)文段45丟失或損壞了民宿,這一點(diǎn)無法從該輸出上進(jìn)行辨認(rèn)娇妓。能夠在主機(jī)slip上看到的是對(duì)第6657字節(jié)(報(bào)文段58)以前數(shù)據(jù)的確認(rèn)(不包括字節(jié)6657在內(nèi))。緊接著的是帶有相同序號(hào)的8個(gè)ACK活鹰。正是接收到報(bào)文段62哈恰,也就是第3個(gè)重復(fù)ACK,才引起自序號(hào)6657開始的數(shù)據(jù)報(bào)文段(報(bào)文段63)進(jìn)行重傳志群。的確着绷,源于伯克利的TCP實(shí)現(xiàn)對(duì)收到的重復(fù)ACK進(jìn)行計(jì)數(shù),當(dāng)收到第3個(gè)時(shí)锌云,就假定一個(gè)報(bào)文段已經(jīng)丟失并重傳自那個(gè)序號(hào)起的一個(gè)報(bào)文段荠医。這就是Jacobson的快速重傳算法,該算法通常與他的快速恢復(fù)算法一起配合使用桑涎。我們?cè)诘?1.7節(jié)中介紹這兩個(gè)算法彬向。

注意到在重傳后(報(bào)文段63),發(fā)送方繼續(xù)正常的數(shù)據(jù)傳輸(報(bào)文段67攻冷、69和71)娃胆。TCP不需要等待對(duì)方確認(rèn)重傳。

現(xiàn)在檢查一下在接收端發(fā)生了什么等曼。當(dāng)按序收到正常數(shù)據(jù)(報(bào)文段43)后里烦,接收TCP將255個(gè)字節(jié)的數(shù)據(jù)交給用戶進(jìn)程凿蒜。但下一個(gè)收到的報(bào)文段(報(bào)文段46)是失序的:數(shù)據(jù)的開始序號(hào)(6913)并不是下一個(gè)期望的序號(hào)(6657)。TCP保存256字節(jié)的數(shù)據(jù)胁黑,并返回一個(gè)已成功接收數(shù)據(jù)的最大序號(hào)加1(6657)的ACK废封。被vangogh接收到的后面7個(gè)報(bào)文段(48,50,52,54,55,57和59)也是失序的,接收方TCP保存這些數(shù)據(jù)并產(chǎn)生重復(fù)ACK丧蘸。

目前TCP尚無辦法告訴對(duì)方缺少一個(gè)報(bào)文段漂洋,也無法確認(rèn)失序數(shù)據(jù)。此時(shí)主機(jī)vangogh所能夠做的就是繼續(xù)發(fā)送確認(rèn)序號(hào)為6657的ACK触趴。

當(dāng)缺少的報(bào)文段(報(bào)文段63)到達(dá)時(shí)氮发,接收方TCP在其緩存中保存第6657~8960字節(jié)的數(shù)據(jù),并將這2304字節(jié)的數(shù)據(jù)交給用戶進(jìn)程冗懦。所有這些數(shù)據(jù)在報(bào)文段72中進(jìn)行確認(rèn)爽冕。請(qǐng)注意此時(shí)該ACK通告窗口大小為5888(8192-2304),這是因?yàn)橛脩暨M(jìn)程沒有機(jī)會(huì)讀取這些已準(zhǔn)備好的2304字節(jié)的數(shù)據(jù)披蕉。

如果仔細(xì)檢查圖21-6中tcpdump的輸出中第14和21秒附近的下垂點(diǎn)颈畸,我們會(huì)看到它們也是由于收到了3個(gè)重復(fù)ACK引起的,這表明一個(gè)分組已經(jīng)丟失没讲。在這些例子中只有一個(gè)分組被重傳眯娱。

在介紹完擁塞避免算法后,將在第21.8節(jié)中繼續(xù)討論這個(gè)例子爬凑。

21.6 擁塞避免算法

在第20.6節(jié)介紹的慢啟動(dòng)算法是在一個(gè)連接上發(fā)起數(shù)據(jù)流的方法徙缴,但有時(shí)我們會(huì)達(dá)到中間路由器的極限,此時(shí)分組將被丟棄嘁信。擁塞避免算法是一種處理丟失分組的方法于样。該方法的具體描述見[Jacobson 1988]。

該算法假定由于分組受到損壞引起的丟失是非常少的(遠(yuǎn)小于1%)潘靖,因此分組丟失就意味著在源主機(jī)和目的主機(jī)之間的某處網(wǎng)絡(luò)上發(fā)生了擁塞穿剖。有兩種分組丟失的指示:發(fā)生超時(shí)和接收到重復(fù)的確認(rèn)(我們?cè)?1.5節(jié)看到這種現(xiàn)象。如果使用超時(shí)作為擁塞指示卦溢,則需要使用一個(gè)好的RT T算法糊余,正如在21.3節(jié)中描述的那樣)。

擁塞避免算法和慢啟動(dòng)算法是兩個(gè)目的不同单寂、獨(dú)立的算法贬芥。但是當(dāng)擁塞發(fā)生時(shí),我們希望降低分組進(jìn)入網(wǎng)絡(luò)的傳輸速率宣决,于是可以調(diào)用慢啟動(dòng)來作到這一點(diǎn)誓军。在實(shí)際中這兩個(gè)算法通常在一起實(shí)現(xiàn)。

擁塞避免算法和慢啟動(dòng)算法需要對(duì)每個(gè)連接維持兩個(gè)變量:一個(gè)擁塞窗口cwnd和一個(gè)慢啟動(dòng)門限ssthresh疲扎。這樣得到的算法的工作過程如下:

1:對(duì)一個(gè)給定的連接昵时,初始化cwnd為1個(gè)報(bào)文段,ssthresh為65535個(gè)字節(jié)椒丧。

2:TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小壹甥。擁塞避免是發(fā)送方使用的流量控制,而通告窗口則是接收方進(jìn)行的流量控制壶熏。前者是發(fā)送方感受到的網(wǎng)絡(luò)擁塞的估計(jì)句柠,而后者則與接收方在該連接上的可用緩存大小有關(guān)。

3:當(dāng)擁塞發(fā)生時(shí)(超時(shí)或收到重復(fù)確認(rèn))棒假,ssthresh被設(shè)置為當(dāng)前窗口大小的一半(cwnd和接收方通告窗口大小的最小值溯职,但最少為2個(gè)報(bào)文段)。此外帽哑,如果是超時(shí)引起了擁塞谜酒,則cwnd被設(shè)置為1個(gè)報(bào)文段(這就是慢啟動(dòng))。

4:當(dāng)新的數(shù)據(jù)被對(duì)方確認(rèn)時(shí)妻枕,就增加cwnd僻族,但增加的方法依賴于我們是否正在進(jìn)行慢啟動(dòng)或擁塞避免。如果cwnd小于或等于ssthresh屡谐,則正在進(jìn)行慢啟動(dòng)述么,否則正在進(jìn)行擁塞避免。慢啟動(dòng)一直持續(xù)到我們回到當(dāng)擁塞發(fā)生時(shí)所處位置的半時(shí)候才停止(因?yàn)槲覀冇涗浟嗽诓襟E2中給我們制造麻煩的窗口大小的一半)愕掏,然后轉(zhuǎn)為執(zhí)行擁塞避免度秘。

慢啟動(dòng)算法初始設(shè)置cwnd為1個(gè)報(bào)文段,此后每收到一個(gè)確認(rèn)就加1饵撑。正如20.6節(jié)描述的那樣剑梳,這會(huì)使窗口按指數(shù)方式增長(zhǎng):發(fā)送1個(gè)報(bào)文段,然后是2個(gè)肄梨,接著是4個(gè)......阻荒。

擁塞避免算法要求每次收到一個(gè)確認(rèn)時(shí)將cwnd增加1/cwnd。與慢啟動(dòng)的指數(shù)增加比起來众羡,這是一種加性增長(zhǎng)(additive increase)侨赡。我們希望在一個(gè)往返時(shí)間內(nèi)最多為cwnd增加1個(gè)報(bào)文段(不管在這個(gè)RTT中收到了多少個(gè)ACK),然而慢啟動(dòng)將根據(jù)這個(gè)往返時(shí)間中所收到的確認(rèn)的個(gè)數(shù)增加cwnd粱侣。

所有的4.3BSD版本和4.4BSD都在擁塞避免中將增加值不正確地設(shè)置為1個(gè)報(bào)文段的一小部分(即一個(gè)報(bào)文段的大小除以8)羊壹,這是錯(cuò)誤的,并在以后的版本中不再使用[Floyd 1994]齐婴。但是油猫,為了和(不正確的)實(shí)現(xiàn)的結(jié)果對(duì)應(yīng),我們?cè)趯淼挠?jì)算中給出了這個(gè)細(xì)節(jié)柠偶。


在[Leffler et al.1989]中介紹的4.3BSD Tahoe版本僅在對(duì)方處于一個(gè)不同的網(wǎng)絡(luò)上時(shí)才進(jìn)行慢啟動(dòng)情妖。而4.3BSD Reno版本改變了這種做法睬关,因此,慢啟動(dòng)總是被執(zhí)行毡证。

圖21-8是慢啟動(dòng)和擁塞避免的一個(gè)可視化描述电爹。我們以段為單位來顯示cwnd和ssthresh,但它們實(shí)際上都是以字節(jié)為單位進(jìn)行維護(hù)的料睛。

圖21-8 慢啟動(dòng)和擁塞避免的可視化描述

在該圖中丐箩,假定當(dāng)cwnd為32個(gè)報(bào)文段時(shí)就會(huì)發(fā)生擁塞。于是設(shè)置ssthresh為16個(gè)報(bào)文段恤煞,而cwnd為1個(gè)報(bào)文段屎勘。在時(shí)刻0發(fā)送了一個(gè)報(bào)文段,并假定在時(shí)刻1接收到它的ACK居扒,此時(shí)cwnd增加為2概漱。接著發(fā)送了2個(gè)報(bào)文段,并假定在時(shí)刻2接收到它們的ACK苔货,于是cwnd增加為4(對(duì)每個(gè)ACK增加1次)犀概。這種指數(shù)增加算法一直進(jìn)行到在時(shí)刻3和4之間收到8個(gè)ACK后cwnd等于ssthresh時(shí)才停止,從該時(shí)刻起夜惭,cwnd以線性方式增加姻灶,在每個(gè)往返時(shí)間內(nèi)最多增加1個(gè)報(bào)文段。

正如我們?cè)谶@個(gè)圖中看到的那樣诈茧,術(shù)語(yǔ)“慢啟動(dòng)”并不完全正確产喉。它只是采用了比引起擁塞更慢些的分組傳輸速率,但在慢啟動(dòng)期間進(jìn)入網(wǎng)絡(luò)的分組數(shù)增加的速率仍然是在增加的敢会。只有在達(dá)到ssthresh擁塞避免算法起作用時(shí)曾沈,這種增加的速率才會(huì)慢下來。

21.7 快速重傳與快速恢復(fù)算法

擁塞避免算法的修改建議1990年提出[Jacobson 1990b]鸥昏。在我們的例子(見21.5節(jié))中已經(jīng)可以看到這些實(shí)施中的修改塞俱。

在介紹修改之前,我們認(rèn)識(shí)到在收到一個(gè)失序的報(bào)文段時(shí)吏垮,TCP立即需要產(chǎn)生一個(gè)ACK(一個(gè)重復(fù)的ACK)障涯。這個(gè)重復(fù)的ACK不應(yīng)該被遲延。該重復(fù)的ACK的在于讓對(duì)方知道收到一個(gè)失序的報(bào)文段膳汪,并告訴對(duì)方自己希望收到的序號(hào)唯蝶。

由于我們不知道一個(gè)重復(fù)的ACK是由一個(gè)丟失的報(bào)文段引起的,還是由于僅僅出現(xiàn)了幾個(gè)報(bào)文段的重新排序遗嗽,因此我們等待少量重復(fù)的ACK到來粘我。假如這只是一些報(bào)文段的重新排序,則在重新排序的報(bào)文段被處理并產(chǎn)生一個(gè)新的ACK之前痹换,只可能產(chǎn)生1~2個(gè)重復(fù)的ACK征字。如果一連串收到3個(gè)或3個(gè)以上的重復(fù)ACK都弹,就非常可能是一個(gè)報(bào)文段丟失了(我們?cè)?1.5節(jié)中見到過這種現(xiàn)象)柔纵。于是我們就重傳丟失的數(shù)據(jù)報(bào)文段缔杉,而無需等待超時(shí)定時(shí)器溢出。這就是快速重傳算法搁料。接下來執(zhí)行的不是慢啟動(dòng)算法而是擁塞避免算法。這就是快速恢復(fù)算法系羞。

在圖21-7中可以看到在收到3個(gè)重復(fù)的ACK之后沒有執(zhí)行慢啟動(dòng)郭计。相反,發(fā)送方進(jìn)行重傳椒振,接著在收到重傳的ACK以前昭伸,發(fā)送了3個(gè)新的數(shù)據(jù)的報(bào)文段(報(bào)文段67,69和71)。

在這種情況下沒有執(zhí)行慢啟動(dòng)的原因是由于收到重復(fù)的ACK不僅僅告訴我們一個(gè)分組丟失了澎迎。由于接收方只有在收到另一個(gè)報(bào)文段時(shí)才會(huì)產(chǎn)生重復(fù)的ACK庐杨,而該報(bào)文段已經(jīng)離開了網(wǎng)絡(luò)并進(jìn)入了接收方的緩存。也就是說夹供,在收發(fā)兩端之間仍然有流動(dòng)的數(shù)據(jù)灵份,而我們不想執(zhí)行慢啟動(dòng)來突然減少數(shù)據(jù)流。

這個(gè)算法通常按如下過程進(jìn)行實(shí)現(xiàn):

1:當(dāng)收到第3個(gè)重復(fù)的ACK時(shí)哮洽,將ssthresh設(shè)置為當(dāng)前擁塞窗口cwnd的一半填渠。重傳丟失的報(bào)文段。設(shè)置cwnd為ssthresh加上3倍的報(bào)文段大小鸟辅。

2:每次收到另一個(gè)重復(fù)的ACK時(shí)氛什,cwnd增加1個(gè)報(bào)文段大小并發(fā)送1個(gè)分組(如果新的cwnd允許發(fā)送)。

3:當(dāng)下一個(gè)確認(rèn)新數(shù)據(jù)的ACK到達(dá)時(shí)匪凉,設(shè)置cwnd為ssthresh(在第1步中設(shè)置的值)枪眉。這個(gè)ACK應(yīng)該是在進(jìn)行重傳后的一個(gè)往返時(shí)間內(nèi)對(duì)步驟1中重傳的確認(rèn)。另外再层,這個(gè)ACK也應(yīng)該是對(duì)丟失的分組和收到的第1個(gè)重復(fù)的ACK之間的所有中間報(bào)文段的確認(rèn)贸铜。這一步采用的是擁塞避免,因?yàn)楫?dāng)分組丟失時(shí)我們將當(dāng)前的速率減半树绩。

在下一節(jié)中我們將看到變量cwnd和ssthresh的計(jì)算過程萨脑。

快速重傳算法最早出現(xiàn)在4.3BSD Ta hoe版本中,但它隨后錯(cuò)誤地使用了慢啟動(dòng)饺饭〔吃纾快速恢復(fù)算法出現(xiàn)在4.3BSD Reno版本中。

21.8 擁塞舉例(續(xù))

通過使用tcmdump和插口排錯(cuò)選項(xiàng)(在第21.4節(jié)進(jìn)行了介紹)來觀察一個(gè)連接瘫俊,就會(huì)在發(fā)送每一個(gè)報(bào)文段時(shí)看到cwnd和ssthresh的值鹊杖。如果MSS為256字節(jié)悴灵,則cwnd和ssthresh的初始值分別為256和65535字節(jié)。每當(dāng)收到一個(gè)ACK時(shí)骂蓖,我們可以看到cwnd增加了一個(gè)MSS积瞒,取值分別為512,768,1024,1280等。假定不會(huì)發(fā)生擁塞登下,則最終擁塞窗口將超過接收方的通告窗口茫孔,意味著通告窗口將對(duì)數(shù)據(jù)流進(jìn)行限制。

一個(gè)更有趣的例子是觀察在擁塞發(fā)生時(shí)的情況被芳。使用與21.4節(jié)同樣的例子缰贝。當(dāng)這個(gè)例子運(yùn)行時(shí)發(fā)生了4次擁塞。為建立連接而發(fā)送的初始SYN有一個(gè)因超時(shí)而引起的重傳(見圖21-5)畔濒,接著在數(shù)據(jù)傳輸過程中有3個(gè)分組丟失(見圖21-6)剩晴。

圖21-9顯示了當(dāng)初始SYN重傳并接著發(fā)送了前7個(gè)數(shù)據(jù)報(bào)文段時(shí)變量cwnd和ssthresh的值(在圖21-2中顯示了最初的數(shù)據(jù)報(bào)文段及其ACK之間的交換過程)。使用tcpdump的記號(hào)來表示數(shù)據(jù)字節(jié):1:257(256)表示第1~256字節(jié)侵状。

當(dāng)SYN的超時(shí)發(fā)生時(shí)赞弥,ssthresh被置為其最小取值(512字節(jié),在本例中表示2個(gè)報(bào)文段)趣兄。為進(jìn)入慢啟動(dòng)階段绽左,cwnd被置為1個(gè)報(bào)文段(256字節(jié),與當(dāng)前值一致)诽俯。

當(dāng)收到SYN和ACK時(shí)妇菱,沒有對(duì)這兩個(gè)變量做任何修改,因?yàn)樾碌臄?shù)據(jù)還沒有被確認(rèn)暴区。

當(dāng)ACK 257到達(dá)時(shí)闯团,因?yàn)閏wnd小于等于ssthresh,因此仍然處于慢啟動(dòng)階段仙粱,于是將cwnd增加256字節(jié)房交。當(dāng)收到ACK 513時(shí),進(jìn)行同樣的處理伐割。

當(dāng)ACK 769到達(dá)時(shí)候味,我們不再處于慢啟動(dòng)狀態(tài),而是進(jìn)入了擁塞避免狀態(tài)隔心。新的cwnd值按以下方法計(jì)算:

考慮到cwnd實(shí)際上以字節(jié)而非以報(bào)文段來維護(hù)白群,因此這就是我們前面提到的增加1/cwnd。在這個(gè)例子中我們計(jì)算

為885字節(jié)(使用整數(shù)算法)硬霍。當(dāng)下一個(gè)ACK 1025到達(dá)時(shí)帜慢,我們計(jì)算


為991字節(jié)(在這些表達(dá)式中包括了不正確的256/8項(xiàng)來匹配實(shí)現(xiàn)計(jì)算的數(shù)值,正如我們?cè)谇懊鏄?biāo)注的那樣)。

圖21-9 擁塞避免的例子

這個(gè)cwnd持續(xù)增加一直到在圖21-6所示的發(fā)生在10秒左右的第1次重傳粱玲。圖21-10是使用與圖21-6相同數(shù)據(jù)得到的圖表躬柬,并給出了cwnd增加的數(shù)值。

本圖中cwnd的前6個(gè)值就是我們?yōu)閳D21-9所計(jì)算的數(shù)值抽减。在這個(gè)圖中允青,要想直觀分辨出在慢啟動(dòng)過程中的指數(shù)增加和在擁塞避免過程中的線性增加之間的區(qū)別是不可能的,因?yàn)槁龁?dòng)的過程太快卵沉。

我們需要解釋在重傳的3個(gè)點(diǎn)上所發(fā)生的情況颠锉。回想起每個(gè)重傳都是因?yàn)槭盏?個(gè)重復(fù)的ACK史汗,表明1個(gè)分組丟失了木柬。這就是21.7節(jié)的快速重傳算法。ssthresh立即設(shè)置為當(dāng)重傳發(fā)生時(shí)正在起作用的窗口大小的一半淹办,但是在接收到重復(fù)ACK的過程中cwnd允許保持增加,這是因?yàn)槊總€(gè)重復(fù)的ACK表示1個(gè)報(bào)文段已離開了網(wǎng)絡(luò)(接收TCP已緩存了這個(gè)報(bào)文段恶复,等待所缺數(shù)據(jù)的到達(dá))怜森。這就是快速恢復(fù)算法。

與圖20-9類似谤牡,圖21-10表示了cwnd和ssthresh的數(shù)值副硅。第一列上的報(bào)文段編號(hào)與圖21-7對(duì)應(yīng)。

圖21-10 當(dāng)數(shù)據(jù)被發(fā)送時(shí)的發(fā)送序號(hào)和cwnd的取值
圖21-11 擁塞避免的例子

cwnd的值一直持續(xù)增加翅萤,從圖21-9中對(duì)應(yīng)于報(bào)文段12的最終取值(1089)到圖21-11中對(duì)應(yīng)于報(bào)文段58的第一個(gè)取值(2426)恐疲,而ssthresh的值則保持不變(512),這是因?yàn)樵诖诉^程中沒有出現(xiàn)過重傳套么。

當(dāng)最初的2個(gè)重復(fù)的ACK(報(bào)文段60和61)到達(dá)時(shí)它們被計(jì)數(shù)培己,而cwnd保持不變(也就是圖21-10中處理重傳之前的平坦的一段)。然而胚泌,當(dāng)?shù)?個(gè)重復(fù)的ACK到達(dá)時(shí)省咨,ssthresh被置為cwnd的一半(四舍五入到報(bào)文段大小的下一個(gè)倍數(shù)),而cwnd被置為ssthresh加上所收到的重復(fù)的ACK數(shù)乘以報(bào)文段大戌枋摇(也即1024加上3倍的256)零蓉,然后發(fā)送重傳數(shù)據(jù)。

又有5個(gè)重復(fù)的ACK到達(dá)(報(bào)文段64~66,68和70)穷缤,每次cwnd增加1個(gè)報(bào)文段長(zhǎng)度敌蜂。最后一個(gè)新的ACK(報(bào)文段72段)到達(dá)時(shí),cwnd被置為ssthresh(1024)并進(jìn)入正常的擁塞避免過程津肛。由于cwnd小于等于ssthresh(現(xiàn)在相等)章喉,因此報(bào)文段的大小增加到cwnd,取值為1280。當(dāng)下一個(gè)新的ACK到達(dá)(沒有在圖21-11中表示出來)時(shí)囊陡,cwnd大于ssthresh芳绩,取值為1363。

在快速重傳和快速恢復(fù)階段撞反,我們收到報(bào)文段66妥色、68和70中的重復(fù)的ACK后才發(fā)送新的數(shù)據(jù),而不是在接收到報(bào)文段64和65中重復(fù)的ACK之后就發(fā)送遏片。這是cwnd的取值與未被確認(rèn)的數(shù)據(jù)大小比較的結(jié)果嘹害。當(dāng)報(bào)文段65到達(dá)時(shí),cwnd為2048吮便,但未被確認(rèn)的數(shù)據(jù)有2304字節(jié)(9個(gè)報(bào)文段:46,48,50,52,54,55,57,59和63)笔呀,因此不能發(fā)送任何數(shù)據(jù)。當(dāng)報(bào)文段65到達(dá)后髓需,cwnd被置為2304许师,此時(shí)我們?nèi)圆荒苓M(jìn)行發(fā)送。但是當(dāng)報(bào)文段66到達(dá)時(shí)僚匆,cwnd為2560微渠,所以我們可以發(fā)送1個(gè)新的數(shù)據(jù)報(bào)文段。類似地咧擂,當(dāng)報(bào)文段68到達(dá)時(shí)逞盆,cwnd等于2816,該數(shù)值大于未被確認(rèn)的2560字節(jié)的數(shù)據(jù)大小松申,因此我們可以發(fā)送另1個(gè)新的數(shù)據(jù)報(bào)文段云芦。報(bào)文段70到達(dá)時(shí)也進(jìn)行了類似的處理。

在圖21-10中的時(shí)刻14.3發(fā)生下一個(gè)重傳贸桶,也是因?yàn)槭盏搅?個(gè)重復(fù)的ACK舅逸。因此當(dāng)另一個(gè)ACK到達(dá)時(shí),可以看到cwnd以同樣的方式增長(zhǎng)刨啸,之后降低到1024堡赔。

圖21-10中的時(shí)刻21.1也是因?yàn)槭盏搅酥貜?fù)的ACK而引起了重傳。在重傳后收到了3個(gè)重復(fù)的ACK设联,因此觀察到cwnd增加3個(gè)善已,之后降低到1280。在傳輸?shù)暮竺娌糠掷肜琧wnd以線性方式增加到最終值3615换团。

21.9 按每條路由進(jìn)行度量

較新的TCP實(shí)現(xiàn)在路由表項(xiàng)中維持許多我們?cè)诒菊乱呀?jīng)介紹過的指標(biāo)。當(dāng)一個(gè)TCP連接關(guān)閉時(shí)宫蛆,如果已經(jīng)發(fā)送了足夠多的數(shù)據(jù)來獲得有意義統(tǒng)計(jì)資料艘包,且目的結(jié)點(diǎn)的路由表項(xiàng)不是一個(gè)默認(rèn)的表項(xiàng)的猛,那么下列信息就保存在路由表項(xiàng)中以備下次使用:被平滑的RTT、被平滑的均值偏差以及慢啟動(dòng)門限想虎。所謂“足夠多的數(shù)據(jù)”是指16個(gè)窗口的數(shù)據(jù)圾亏,這樣就可得到16個(gè)RTT采樣姻蚓,從而使被平滑的RT T過濾器能夠集中在正確結(jié)果的5%以內(nèi)卷员。

而且井氢,管理員可以使用route(8)命令來設(shè)置給定路由的度量:前一段中給出的三個(gè)指標(biāo)以及MT、輸出的帶寬時(shí)延乘積(見第20.7節(jié))和輸入的帶寬時(shí)延乘積裙椭。

當(dāng)建立一個(gè)新的連接時(shí)躏哩,不論是主動(dòng)還是被動(dòng),如果該連接將要使用的路由表項(xiàng)已經(jīng)有這些度量的值揉燃,則用這些度量來對(duì)相應(yīng)的變量進(jìn)行初始化扫尺。

21.10 ICMP的差錯(cuò)

讓我們來看一下TCP是怎樣處理一個(gè)給定的連接返回的ICMP的差錯(cuò)。TCP能夠遇到的最常見的ICMP差錯(cuò)就是源站抑制炊汤、主機(jī)不可達(dá)和網(wǎng)絡(luò)不可達(dá)正驻。

當(dāng)前基于伯克利的實(shí)現(xiàn)對(duì)這些錯(cuò)誤的處理是:

一個(gè)接收到的源站抑制引起擁塞窗口cwnd被置為1個(gè)報(bào)文段大小來發(fā)起慢啟動(dòng),但是慢啟動(dòng)門限ssthresh沒有變化抢腐,所以窗口將打開直至它或者開放了所有的通路(受窗口大小和往返時(shí)間的限制)或者發(fā)生了擁塞拨拓。

一個(gè)接收到的主機(jī)不可達(dá)或網(wǎng)絡(luò)不可達(dá)實(shí)際上都被忽略,因?yàn)檫@兩個(gè)差錯(cuò)都被認(rèn)為是短暫現(xiàn)象氓栈。這有可能是由于中間路由器被關(guān)閉而導(dǎo)致選路協(xié)議要花費(fèi)數(shù)分鐘才能穩(wěn)定到另一個(gè)替換路由。在這個(gè)過程中就可能發(fā)生這兩個(gè)ICMP差錯(cuò)中的一個(gè)婿着,但是連接并不必被關(guān)閉授瘦。相反,TCP試圖發(fā)送引起該差錯(cuò)的數(shù)據(jù)竟宋,盡管最終有可能會(huì)超時(shí)(回想圖21-1中TCP在9分鐘內(nèi)沒有放棄的情況)提完。當(dāng)前基于伯克利的實(shí)現(xiàn)記錄發(fā)生的ICMP差錯(cuò),如果連接超時(shí)丘侠,ICMP差錯(cuò)被轉(zhuǎn)換為一個(gè)更合適的的差錯(cuò)碼而不是“連接超時(shí)”徒欣。

早期的BSD實(shí)現(xiàn)在任何時(shí)候收到一個(gè)主機(jī)不可達(dá)或網(wǎng)絡(luò)不可達(dá)的ICMP差錯(cuò)時(shí)會(huì)不正確的放棄連接。

一個(gè)例子

可以通過在連接中撥號(hào)SLIP鏈路的斷開來觀察一個(gè)ICMP主機(jī)不可達(dá)的差錯(cuò)是如何被處理的蜗字。建立一個(gè)從主機(jī)slip到主機(jī)aix的連接(從扉頁(yè)前的圖中可以看到這個(gè)連接經(jīng)過了我們的撥號(hào)SLIP鏈路)打肝。在建立連接并發(fā)送一些數(shù)據(jù)之后,在路由器sun和netb之間的SLIP鏈路被斷開挪捕,這引起sun上的默認(rèn)路由表項(xiàng)(見9.2節(jié))被移去粗梭。我們希望sun對(duì)目的為140.252.1以太網(wǎng)的IP數(shù)據(jù)報(bào)響應(yīng)ICMP主機(jī)不可達(dá)。希望觀察TCP如何處理這些ICMP差錯(cuò)级零。

下面是主機(jī)slip的交互會(huì)話:



圖21-12顯示了在路由器bsdi上截獲的tcpdump的相應(yīng)輸出(去掉了連接建立和所有的窗口通告)断医。我們連接到在主機(jī)aix上的回顯服務(wù)器并鍵入“test line”(第1行),它被回顯(第2行)且回顯被確認(rèn)(第3行),接著我們斷開了SLIP鏈路鉴嗤。

我們鍵入“another line”(第3行之后)并希望看到TCP超時(shí)和重傳報(bào)文斩启。的確,這一行在收到應(yīng)答前被發(fā)送了6次醉锅。第4~13行顯示了第1次傳輸和接著的4次重傳兔簇,每個(gè)都產(chǎn)生了一個(gè)來自路由器sun的ICMP主機(jī)不可達(dá)。這正是我們所希望的:從slip來的IP數(shù)據(jù)報(bào)發(fā)往路由器bsdi(這是一個(gè)指向sun的默認(rèn)路由器)荣挨,并到達(dá)檢測(cè)到鏈路中斷的sun男韧。

在發(fā)生這些重傳時(shí),SLIP鏈路又被連通默垄,在第14行的重傳被交付此虑。第15行是來自aix的回顯,而第16行是對(duì)這個(gè)回顯的確認(rèn)口锭。

這表明TCP忽略ICMP主機(jī)不可達(dá)的差錯(cuò)并堅(jiān)持重傳朦前。我們也可以觀察到所預(yù)期的在每一次重傳超時(shí)中的指數(shù)退避:第1次約為2.5秒,接著乘2(約5秒)鹃操,乘4(約10秒)韭寸,乘8(約20秒),乘14(約40秒)荆隘。

接著我們鍵入輸入的第3行(“l(fā)ine number 3”)并看到它在第17行被發(fā)送恩伺,在第18行回顯,并在第19行對(duì)回顯進(jìn)行確認(rèn)椰拒。


圖21-12 TCP對(duì)接收到的ICMP主機(jī)不可達(dá)差錯(cuò)的處理

現(xiàn)在我們希望觀察在接收到ICMP主機(jī)不可達(dá)后晶渠,TCP重傳并放棄的情況。于是再次斷開SLIP鏈路燃观,之后鍵入“the last line”褒脯,并觀察到在TCP放棄之前該行被發(fā)送了13次(我們已經(jīng)從結(jié)果中刪除了第30~43行,它們是額外的重傳)缆毁。

然而番川,我們所觀察到的現(xiàn)象是sock程序在最終放棄時(shí)打印出來的差錯(cuò)信息:“沒有到達(dá)主機(jī)的路由”。這與Unix的ICMP主機(jī)不可達(dá)的差錯(cuò)類似(圖6-12)脊框。這表明TCP保存了它在連接上收到的ICMP差錯(cuò)颁督,并在最終放棄時(shí)打印出該差錯(cuò),而不是“連接超時(shí)”浇雹。

最后适篙,注意到第2246行與第614行不同的重傳間隔◇镆看起來我們鍵入的第3行在第17~19行被發(fā)送和確認(rèn)時(shí)(無任何重傳)嚷节,TCP更新了它的估計(jì)器聂儒。最初的重傳超時(shí)時(shí)間現(xiàn)在是3秒,后續(xù)取值為6,12,24,48硫痰,直至上限64衩婚。

21.11 重新分組

當(dāng)TCP超時(shí)并重傳時(shí),它不一定要重傳同樣的報(bào)文段效斑。相反非春,TCP允許進(jìn)行重新分組而發(fā)送一個(gè)較大的報(bào)文段,這將有助于提高性能(當(dāng)然缓屠,這個(gè)較大的報(bào)文段不能夠超過接收方聲明的MSS)奇昙。在協(xié)議中這是允許的,因?yàn)門CP是使用字節(jié)序號(hào)而不是報(bào)文段序號(hào)來進(jìn)行識(shí)別它所要發(fā)送的數(shù)據(jù)和進(jìn)行確認(rèn)敌完。

在實(shí)際中储耐,可以很容易地看到這一點(diǎn)。我們使用sock程序連接到丟棄服務(wù)器并鍵入一行滨溉。接著拔掉以太網(wǎng)電纜并再鍵入一行什湘。當(dāng)這一行被重傳時(shí),鍵入第3行晦攒。我們預(yù)期下一個(gè)重傳包含第2次和第3次鍵入的數(shù)據(jù)闽撤。

圖21-13顯示了tcpdump的輸出(去掉了連接建立、連接終止以及所有的窗口通告)脯颜。

圖21-13 TCP對(duì)數(shù)據(jù)的重新分組

第1行和第2行顯示了頭一行(“hello there”)被發(fā)送及其ACK哟旗。接著我們拔掉以太網(wǎng)電纜并鍵入“l(fā)ine number 2”(14字節(jié),包括換行)栋操。這些數(shù)據(jù)在第3行被發(fā)送热幔,并在第4和第5行被重傳。

在第6行重傳前讼庇,我們鍵入“and 3”(6個(gè)字節(jié),包括換行)近尚,并觀察到這個(gè)重傳包括20個(gè)字節(jié):鍵入的兩行蠕啄。當(dāng)ACK在第9行到達(dá)時(shí),它確認(rèn)了這20字節(jié)的數(shù)據(jù)戈锻。

21.12 小結(jié)

本章提供了對(duì)TCP超時(shí)和重傳機(jī)制的詳細(xì)研究歼跟。使用的第1個(gè)例子是一個(gè)丟失的建立連接的SYN,并觀察了在隨后的重傳和超時(shí)中怎樣使用指數(shù)退避方式格遭。

TCP計(jì)算往返時(shí)間并使用這些測(cè)量結(jié)果來維護(hù)一個(gè)被平滑的RT T估計(jì)器和被平滑的均值偏差估計(jì)器哈街。這兩個(gè)估計(jì)器用來計(jì)算下一個(gè)重傳時(shí)間。許多實(shí)現(xiàn)對(duì)每個(gè)窗口僅測(cè)量一次RT T拒迅。Karn算法在分組丟失時(shí)可以不測(cè)量RT T就能解決重傳的二義性問題骚秦。

詳細(xì)例子包括3個(gè)丟失的分組她倘,使我們看到TCP的許多實(shí)際算法:慢啟動(dòng)、擁塞避免作箍、快速重傳和快速恢復(fù)硬梁。我們也能夠使用擁塞窗口和慢啟動(dòng)門限來手工計(jì)算TCP RTT估計(jì)器,并將這些值與跟蹤輸出的實(shí)際數(shù)據(jù)進(jìn)行比較胞得。

以多種ICMP差錯(cuò)對(duì)TCP連接的影響以及TCP怎樣允許對(duì)數(shù)據(jù)進(jìn)行重新分組來結(jié)束本章荧止。我們觀察到“軟”的ICMP差錯(cuò)沒有引起TCP連接終止,但這些差錯(cuò)被保存以便在連接非正常中止時(shí)能夠報(bào)告這些軟差錯(cuò)阶剑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末跃巡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子牧愁,更是在濱河造成了極大的恐慌素邪,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件递宅,死亡現(xiàn)場(chǎng)離奇詭異娘香,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)办龄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門烘绽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人俐填,你說我怎么就攤上這事安接。” “怎么了英融?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵盏檐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我驶悟,道長(zhǎng)胡野,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任痕鳍,我火速辦了婚禮硫豆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笼呆。我一直安慰自己熊响,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布诗赌。 她就那樣靜靜地躺著汗茄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铭若。 梳的紋絲不亂的頭發(fā)上洪碳,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天递览,我揣著相機(jī)與錄音,去河邊找鬼偶宫。 笑死非迹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纯趋。 我是一名探鬼主播憎兽,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼吵冒!你這毒婦竟也來了纯命?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤痹栖,失蹤者是張志新(化名)和其女友劉穎亿汞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揪阿,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疗我,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了南捂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吴裤。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖溺健,靈堂內(nèi)的尸體忽然破棺而出麦牺,到底是詐尸還是另有隱情,我是刑警寧澤鞭缭,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布剖膳,位于F島的核電站,受9級(jí)特大地震影響岭辣,放射性物質(zhì)發(fā)生泄漏吱晒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一沦童、第九天 我趴在偏房一處隱蔽的房頂上張望仑濒。 院中可真熱鬧,春花似錦搞动、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至辅柴,卻和暖如春箩溃,著一層夾襖步出監(jiān)牢的瞬間瞭吃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工涣旨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歪架,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓霹陡,卻偏偏與公主長(zhǎng)得像和蚪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烹棉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 24.1 引言 TCP已經(jīng)在從1200 b/s的撥號(hào)SLIP鏈路到以太數(shù)據(jù)鏈路上運(yùn)行了許多年攒霹。在80年代和90年代...
    張芳濤閱讀 1,486評(píng)論 0 3
  • 20.1 引言 在第15章我們看到TFTP使用了停止等待協(xié)議。數(shù)據(jù)發(fā)送方在發(fā)送下一個(gè)數(shù)據(jù)塊之前需要等待接收對(duì)已發(fā)送...
    張芳濤閱讀 869評(píng)論 0 2
  • 1.這篇文章不是本人原創(chuàng)的浆洗,只是個(gè)人為了對(duì)這部分知識(shí)做一個(gè)整理和系統(tǒng)的輸出而編輯成的催束,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,063評(píng)論 6 174
  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記伏社,這雖然只是...
    貳零壹柒_fc10閱讀 5,054評(píng)論 0 8
  • 我們用websocket和http來研究一下TCP/IP協(xié)議的一些特性抠刺,在上一篇文章《https連接的前幾毫秒發(fā)生...
    極樂君閱讀 1,935評(píng)論 1 6