1 利用滑動窗口實現(xiàn)流量控制
??流量控制就是讓發(fā)送方的發(fā)送速率不要太快,要讓接收方來得及接收唠亚。即發(fā)送方的發(fā)送速率和接收方應(yīng)用程序的讀取速率相匹配灶搜。
??TCP利用滑動窗口機制實現(xiàn)對發(fā)送方的流量控制割卖。在建立連接的三次握手過程中通信雙方協(xié)商一些參數(shù)鹏溯,其中就有窗口值rwnd淹仑,接收方會將自己的接收能力存放字窗口值字段中傳送給發(fā)送方,發(fā)送方根據(jù)這個窗口值設(shè)置發(fā)送窗口的大小平窘。因此發(fā)送方發(fā)送窗口不能超過接收方給出的接收窗口的數(shù)值凳怨。
??TCP的窗口單位是字節(jié)肤舞。
??如下圖所示,現(xiàn)假設(shè)接收方在建立連接告知發(fā)送方自己的接收窗口值是400萨赁,數(shù)據(jù)報文段的序號是從1開始的杖爽。ACK表示確認位慰安,ack表示確認字段的值化焕。一個報文段的長度是100字節(jié)撒桨,圖中發(fā)送窗口中一個窗口表示100字節(jié)凤类。
??(1) 開始時刻的窗口狀態(tài)如下圖所示佃延。
??(2) ① ~ ③表示發(fā)送方發(fā)送了300個字節(jié)夷磕,但是序號為201~300的字節(jié)丟失履肃,發(fā)送方發(fā)送完之后的窗口狀態(tài)如下圖所示。
??(3) ④接收端返回確認報文段坐桩,其中ack = 201尺棋,表示下一個期望收到的報文段序號為201。其中確認報文段中攜帶者接收方給發(fā)送方的接收窗口值為300撕攒,此時發(fā)送窗口的狀態(tài)如下圖所示陡鹃。
??(4) ⑤ ~ ⑦分別發(fā)送了序號301-500的數(shù)據(jù)烘浦,其中丟失的數(shù)據(jù)由于計時器超時,進行了重傳萍鲸,此時窗口已滿闷叉,狀態(tài)如下圖所示。
??(5) ⑧接收方返回對序號201-500的數(shù)據(jù)的確認嘿期,并再次將發(fā)送窗口大小設(shè)置為100個字節(jié)。發(fā)送窗口狀態(tài)如下圖所示。
??(6) ⑨發(fā)送方發(fā)送序號為501-600的數(shù)據(jù),窗口已滿脊串,不能在發(fā)送了循捺,此時狀態(tài)如下础钠。
??(7) ⑩接收方返回確認香府,并將窗口大小設(shè)置為0锭碳,即不讓發(fā)送方發(fā)送數(shù)據(jù)了。
??上述過程中,接收方一共進行了3次流量控制,第一次將窗口大小減小至300,第二次將窗口大小減小至100早直,最后一次將窗口大小設(shè)置為0枫振。
??現(xiàn)在考慮這樣一種情況,接收方在發(fā)送了零窗口的報文段不久之后肆汹,接收方的緩存又有了一些空間扫腺,于是接收方就向發(fā)送方發(fā)送了一個報文段,其中的窗口值為400,表示發(fā)送方又可以發(fā)送數(shù)據(jù)蝙昙,然而這個報文段在傳送的過程中丟失了烈拒,發(fā)送方一直在等待接收方的非零窗口的通知赊时,而接收方一直在等待發(fā)送方的數(shù)據(jù)。如果沒有其他措施,這種相互等待的死鎖局面一致延續(xù)下去。
??為了解決這個問題阿趁,TCP為每個連接設(shè)有一個持續(xù)計時器(persistence timer)砚哆。只要TCP連接的一方收到了對方的零窗口通知战转,就啟動持續(xù)計時器啄踊。若持續(xù)計時器設(shè)置時間到期,就發(fā)送一個探測報文段(僅攜帶1字節(jié)的數(shù)據(jù))启搂,而對方就在確認這個探測報文段時給出了現(xiàn)在的窗口值,如果窗口值仍然是零乡小,那么收到報文段的一方就重新設(shè)置持續(xù)計時器。如果窗口不是零,則死鎖的僵局就打破了。
TCP規(guī)定秀仲,即使設(shè)置窗口為零,也必須接收以下報文段:零窗口探測報文段铝阐、確認報文段和攜帶緊急數(shù)據(jù)的報文段。
2 TCP的傳輸效率
??應(yīng)用進程將數(shù)據(jù)傳送到TCP的發(fā)送緩存后遍蟋,剩下的發(fā)送任務(wù)就由TCP來控制了。可以用不同的機制來控制TCP報文段的發(fā)送時機何乎。
(1) 第一種機制:TCP維持一個變量,它等于最大報文段長度MSS脯燃。只要緩存中存放的數(shù)據(jù)達到MSS字節(jié)扁瓢,就組裝成一個TCP報文段發(fā)送出去伟桅。
(2) 第二種機制:由發(fā)送方的應(yīng)用進程指明要求發(fā)送報文段,即TCP支持推送(push)操作。
(3) 第三種機制:發(fā)送方的一個計時器時限到了乌企,這時就把當(dāng)前已有的緩存數(shù)據(jù)裝入報文段(但長度不能超過MSS)發(fā)送出去。
??前面說過成玫,如果發(fā)送方僅發(fā)送一個字節(jié)數(shù)據(jù)加酵,那么在傳輸過程中對數(shù)據(jù)組裝到網(wǎng)絡(luò)層至少需要41字節(jié)拳喻,當(dāng)在線路帶寬不富裕時,這種傳送方法的效率的確不高猪腕。
??在TCP的實現(xiàn)中廣泛使用Nagle算法冗澈。Nagle算法要求,當(dāng)一個TCP連接中有在傳數(shù)據(jù)(即那些已發(fā)送但還未經(jīng)確認的數(shù)據(jù))陋葡,小的報文段(長度小于MSS)就不能發(fā)送亚亲,將這些小數(shù)據(jù)放入發(fā)送緩存中,直到所有的在傳數(shù)據(jù)都收到了ACK.腐缤。并且捌归,在收到ACK后,TCP需要將緩存中的小數(shù)據(jù)整合到一個報文段中發(fā)送岭粤。這種方法迫使TCP遵循停等協(xié)議——只有在收到所有在傳數(shù)據(jù)的ACK后才能繼續(xù)發(fā)送惜索。該算法的優(yōu)點在于它實現(xiàn)了自時鐘控制:ACK返回的越快,數(shù)據(jù)傳輸?shù)囊簿驮娇?/strong>剃浇。
??Nagle算法還規(guī)定:當(dāng)發(fā)送緩存中的數(shù)據(jù)達到發(fā)送窗口大小的一半或已達到報文段的最大長度時巾兆,就立即發(fā)送下一個報文段。
??在相對高延遲的廣域網(wǎng)中虎囚,更需要減少小報文段的數(shù)目角塑,該算法使得單位時間內(nèi)發(fā)送報文段數(shù)目更少。也就是說RTT控制著發(fā)包速率溜宽。
3 糊涂窗口綜合癥
??基于窗口的流量控制機制吉拳,尤其是不使用大小固定的報文段的情況,可能會出現(xiàn)稱為糊涂窗口綜合癥SWS(Silly Window Syndrome适揉,SWS)
??TCP連接的兩端都有可能導(dǎo)致SWS的出現(xiàn):接收端的通告窗口較辛粼堋(沒有等到窗口變大才通知),或者發(fā)送端發(fā)送的數(shù)據(jù)段較屑掂帧(沒有等待將其他數(shù)據(jù)組合成一個更大的報文段)炼邀。
例如,TCP接收緩存已滿剪侮,而交互式應(yīng)用進程一次只從接收緩存中讀取1個字節(jié)(這樣就使接收緩存僅騰出1個字節(jié))拭宁,然后向發(fā)送方發(fā)送確認,并把窗口設(shè)置為1個字節(jié)瓣俯。接著杰标,發(fā)送方又發(fā)來1個字節(jié)的數(shù)據(jù)。接收方發(fā)回確認彩匕,仍然將窗口設(shè)置為1個字節(jié)腔剂。這樣下去,是網(wǎng)絡(luò)的效率很低驼仪。
??要解決這個問題掸犬,需要遵循以下規(guī)則:
??(1) 對于接收端來說袜漩,可以讓接收方等待一個段時間,使得接收緩存已有足夠的空間容納一個MSS湾碎,或者等待接收緩存已有一半的空閑空間宙攻。
??(2) 對于發(fā)送方來說,不應(yīng)發(fā)送小的報文段介褥,而且需由Nagle算法控制何時發(fā)送座掘,為避免SWS問題,只有至少滿足以下條件之一時才能傳輸報文段:
??1) 全長(發(fā)送MSS字節(jié))的報文段可以發(fā)送呻顽。
??2) 數(shù)據(jù)段長度 ≥ 接收端通告過的窗口值的一半的雹顺,可以發(fā)送。
??3) 滿足以下任一條件的都可以發(fā)送:i) 某一ACK不是目前期盼的(即沒有未被確認的在傳數(shù)據(jù))廊遍;ii) 該連接禁用Nagle算法。
??條件 1) 最直接地避免了高耗費的報文段傳輸問題贩挣。條件 2) 針對通知窗口較小喉前,可能小于要傳輸?shù)膱笪亩蔚那闆r。條件3) 防止TCP在數(shù)據(jù)被確認以及Nagle算法啟用的情況下發(fā)送小的報文段王财。若發(fā)送端應(yīng)用在執(zhí)行某些小的寫操作(如小于報文段大新延亍)。條件3) 可以有效避免SWS绒净。