TCP 可靠傳輸?shù)膶?shí)現(xiàn)(二)TCP的重傳機(jī)制

1塞茅、背景介紹

TCP使用可靠的傳輸協(xié)議亩码,即意味著必須按序、無差錯(cuò)的傳送數(shù)據(jù)到目的端野瘦,那么如果在傳輸過程中發(fā)送的包丟失了該怎么辦描沟?TCP的重傳機(jī)制就是:如果發(fā)送方認(rèn)為發(fā)生了丟包現(xiàn)象就重發(fā)這些數(shù)據(jù)包。顯然鞭光,我們需要一個(gè)方法去猜測是否發(fā)生了丟包吏廉。最簡單的想法就是,接收方每接收到一個(gè)包就向發(fā)送者返回一個(gè)ACK惰许,表示自己已經(jīng)收到了這段數(shù)據(jù)席覆,反過來,如果發(fā)送方一段時(shí)間內(nèi)沒有收到ACK汹买,就知道很可能是數(shù)據(jù)包丟失了佩伤,緊接著就重發(fā)該數(shù)據(jù)包聊倔,直到收到ACK為止。

為什么是猜測呢生巡? 因?yàn)榧词故浅瑫r(shí)了耙蔑,這個(gè)數(shù)據(jù)包也可能并沒有丟,它只是繞了段遠(yuǎn)程孤荣,來的很晚而已甸陌。畢竟TCP協(xié)議是位于傳輸層的協(xié)議,不可能明確知道數(shù)據(jù)鏈路層和物理層發(fā)生了什么垃环。但是這并不妨礙我們的超時(shí)重傳機(jī)制邀层,因?yàn)榻邮辗綍?huì)自動(dòng)忽略收到的重復(fù)的包。

下面我們具體講一講TCP的重傳機(jī)制:

2遂庄、重傳--TCP的重要事件

(1)基于計(jì)時(shí)器的重傳---超時(shí)重傳

這種機(jī)制下寥院,每個(gè)數(shù)據(jù)包都有相應(yīng)的計(jì)時(shí)器,當(dāng)超過指定的時(shí)間后涛目,沒有收到對方的 ACK 確認(rèn)應(yīng)答報(bào)文就會(huì)重發(fā)該數(shù)據(jù)包秸谢。

兩種情況

超時(shí)時(shí)間應(yīng)該設(shè)置為多少

我們先來了解一下 RTT (Round-Trip Time 往返時(shí)延)

RTT

而超時(shí)時(shí)間是以 RTO(Retransmission Timeout 超時(shí)重傳時(shí)間)表示。

超時(shí)時(shí)間不宜設(shè)置的過長或過短霹肝,否則:

超時(shí)時(shí)間設(shè)置過長或過短

綜上可知估蹄,RTO設(shè)置的值應(yīng)該略大于RTT的值。


RTO值的計(jì)算:

https://blog.csdn.net/JXH_123/article/details/27345151

值得注意的是:每觸發(fā)一次超時(shí)重傳沫换,都會(huì)將下一次超時(shí)時(shí)間間隔設(shè)為先前值的兩倍臭蚁。遇到超時(shí)說明網(wǎng)絡(luò)環(huán)境差,不宜頻繁發(fā)送讯赏。

Wireshark 抓包顯示:

超時(shí)重傳

超時(shí)重傳存在的問題是:

\bullet ?當(dāng)一個(gè)報(bào)文段丟失時(shí)垮兑,會(huì)等待一定的超時(shí)時(shí)間后才重傳,增加了端到端的時(shí)延漱挎;

\bullet ?當(dāng)一個(gè)報(bào)文段丟失時(shí)系枪,在其等待超時(shí)的過程中,可能會(huì)出現(xiàn)這種情況: 其后的報(bào)文段已經(jīng)被接收端接收但卻遲遲得不到確認(rèn)磕谅,發(fā)送端就也以為丟失了私爷,從而引起不必要的重傳,既浪費(fèi)時(shí)間也浪費(fèi)資源膊夹。(例如: 數(shù)據(jù)包5丟失衬浑,數(shù)據(jù)包6、7放刨、8嚎卫、9都已到達(dá)接收方,這個(gè)時(shí)候客戶端只能等服務(wù)端發(fā)送ACK,因此對于客戶端來說拓诸,它完全不知道丟了幾個(gè)包,可能就悲觀的認(rèn)為:5后面的數(shù)據(jù)包都丟了麻昼,就重傳這5個(gè)數(shù)據(jù)包奠支,這就比較浪費(fèi)了)。

(2)基于接收方的反饋信息的重傳---快速重傳

剛剛提到過抚芦,基于計(jì)時(shí)器的重傳往往要等待很長時(shí)間倍谜,而快速重傳使用了很巧妙的方法來解決這個(gè)問題。

快速重傳(Fast Retransmit)機(jī)制不以時(shí)間為驅(qū)動(dòng)叉抡,而是以數(shù)據(jù)為驅(qū)動(dòng)重傳尔崔。

由于TCP采用的是累計(jì)確認(rèn)機(jī)制,當(dāng)接收端收到比期望序號大的報(bào)文段時(shí)褥民,便會(huì)重復(fù)發(fā)送最近一次確認(rèn)的報(bào)文段的確認(rèn)號季春,即 冗余 ACK (Duplicate ACK)。

快速重傳機(jī)制

這樣消返,如果在超時(shí)重傳定時(shí)器溢出之前载弄,接收到連續(xù)的三個(gè)重復(fù)冗余 ACK (第一個(gè)ACK是正常的,后三個(gè)是冗余的)撵颊,發(fā)送端便知曉哪個(gè)報(bào)文段在傳輸過程中丟失了宇攻,于是重發(fā)該報(bào)文段,而不需要等待超時(shí)重傳定時(shí)器溢出倡勇,大大提高了效率逞刷。

Wireshark 抓包顯示:

快速重傳

但是,快速重傳仍然沒有解決第二個(gè)問題:到底該重傳多少個(gè)包妻熊?

(3)帶選擇確認(rèn)的重傳---SACK

改進(jìn)的方法就是 SACK (Selective Acknowledgment)夸浅,簡單來說就是在快速重傳的基礎(chǔ)上,返回最近收到的報(bào)文段的序列號范圍固耘,這樣客戶端就知道题篷,哪些數(shù)據(jù)包已經(jīng)到達(dá)服務(wù)器了。

看下例子:


存在 SACK 選項(xiàng)時(shí)

當(dāng)500-599報(bào)文到達(dá)厅目,接收方發(fā)送? ACK 200? 番枚,SACK [500,600)

當(dāng)600-699報(bào)文到達(dá),接收方發(fā)送? ACK 200? 损敷,SACK [500,700)

當(dāng)700-799報(bào)文到達(dá)

當(dāng)800-899報(bào)文到達(dá)

當(dāng)900-999報(bào)文到達(dá)葫笼,接收方累積確認(rèn)發(fā)送? ACK 200? ,SACK [500,1000)

連續(xù)收到3個(gè)重復(fù)ACK拗馒,發(fā)送方經(jīng)檢查發(fā)現(xiàn)200-499的數(shù)據(jù)丟失了路星,執(zhí)行快速重傳,待接收方接收到200-499的數(shù)據(jù),并返回 ACK 1000時(shí)洋丐,發(fā)送方的所有數(shù)據(jù)均已確認(rèn)完畢呈昔,移動(dòng)滑動(dòng)窗口到1000位置處。

使用 SACK可以告知發(fā)送方 收到了哪些數(shù)據(jù)友绝,發(fā)送方收到這些消息后就會(huì)知道哪些數(shù)據(jù)丟失堤尾,然后立即重傳丟失的部分。

需要注意的是:只有收到失序的分組時(shí)才可能會(huì)發(fā)送SACK迁客。

\bullet SACK 包括了兩個(gè)TCP選項(xiàng)郭宝,一個(gè)選項(xiàng)用于標(biāo)識是否支持 SACK(SACK_Permitted),在TCP建立連接時(shí)發(fā)送掷漱;另一種選項(xiàng)則包含了具體的 SACK信息粘室。

(1)SACK_Permitted 選項(xiàng)

該選項(xiàng)只允許在TCP連接建立時(shí),有 SYN標(biāo)志的包中設(shè)置卜范,在連接建立階段衔统,主動(dòng)發(fā)起連接的一方在它的SYN中指定選項(xiàng)。只有在它從另一方的SYN中收到了這個(gè)選項(xiàng)之后先朦,SACK機(jī)制才會(huì)被使能缰冤。

Wireshark抓包SACK選項(xiàng)

(2)SACK 信息選項(xiàng)

SACK 選項(xiàng)參數(shù)告訴對方已經(jīng)接收到并緩存的不連續(xù)的數(shù)據(jù)塊,發(fā)送方可據(jù)此信息檢查究竟是哪個(gè)塊丟失喳魏,從而發(fā)送相應(yīng)的數(shù)據(jù)塊棉浸。

?Left Edge:本區(qū)塊的第一個(gè)序號。 Right Edge:本區(qū)塊的最后序號的下一個(gè)序號刺彩。

[Left Edge, Right Edge)區(qū)間的ACK 序號表示本次確認(rèn)收到的序號迷郑。

問題1:SACK選項(xiàng)最多能包含多少個(gè)需重傳的塊?

?????? 由于TCP首部的最大長度為 60 byte创倔,而固定首部占用了 20 byte嗡害,對于SACK選項(xiàng)本身占用了2 byte,所以剩下 60-20-2=38 byte畦攘。而每個(gè)塊(包括開始和結(jié)束)占用 8 byte霸妹,所以最多可標(biāo)識的塊數(shù)為 38/8 = 4塊,所以 SACK 最多可以包括4個(gè)需重傳的塊知押。同時(shí)由于SACK有些時(shí)候會(huì)和時(shí)間戳(占10字節(jié))一起用叹螟,因此,此種情況下最多只有3個(gè)SACK台盯。

問題2:SACK選項(xiàng)的使用規(guī)則是怎么樣的罢绽?

SACK 的發(fā)送方,即 報(bào)文的接收端

\bullet 第一個(gè)塊需要指出是哪一個(gè)到達(dá)的報(bào)文觸發(fā)的 SACK

\bullet 盡可能多的把所有的塊填滿

\bullet SACK 要報(bào)告最近接收的不連續(xù)的數(shù)據(jù)塊

SACK 的接收端静盅,即 報(bào)文的發(fā)送端:

\bullet 數(shù)據(jù)沒有被確認(rèn)前良价,都會(huì)保持在滑動(dòng)窗口內(nèi)

\bullet 每個(gè)數(shù)據(jù)包都有一個(gè) SACKed 的標(biāo)志,對于已經(jīng)標(biāo)示的報(bào)文,再次接收到時(shí)會(huì)忽略

\bullet ?如果SACK丟失明垢,超時(shí)重傳之后蚣常,重置所有數(shù)據(jù)包SACKed 標(biāo)志

(4)帶重復(fù)選擇確認(rèn)的重傳---DSACK

DSACK是在SACK的基礎(chǔ)上做了一些擴(kuò)展,主要用于對收到的重復(fù)報(bào)文進(jìn)行了處理袖外。

它的主要作用是:告訴發(fā)送方有哪些數(shù)據(jù)被重復(fù)接收了史隆。

DSACK同樣使用了與SACK一樣的報(bào)文格式,唯一區(qū)別在于:第一個(gè)連續(xù)的block指定的是觸發(fā)DSACK的重復(fù)報(bào)文的序號空間曼验。如果第一個(gè)段的范圍被ACK范圍所覆蓋,那么就是DSACK粘姜△拚眨或者,第一個(gè)段的范圍被SACK的第二個(gè)段覆蓋孤紧,那么就是DSACK豺裆。

第一種情況


第二種情況

引入DSACK的好處有:

1)可以讓發(fā)送方知道,是發(fā)出去的包丟了号显,還是回來的ACK包丟了臭猜;


2)是不是自己的 timeout 設(shè)置太小了,導(dǎo)致重傳押蚤;


3)網(wǎng)絡(luò)上出現(xiàn)了先發(fā)的包后到的情況(又稱數(shù)據(jù)包失序)蔑歌;


4)網(wǎng)絡(luò)上是不是把我的數(shù)據(jù)包給復(fù)制了;

總之揽碘,DSACK的目的是幫助發(fā)送方判斷次屠,是否發(fā)生了包失序、ACK丟失雳刺、包重復(fù)或偽重傳劫灶,讓TCP可以更好的做網(wǎng)絡(luò)流量控制。

3掖桦、總結(jié)

超時(shí)重傳機(jī)制能解決數(shù)據(jù)包丟失的問題本昏,但是超時(shí)重傳機(jī)制存在等待時(shí)間太長,浪費(fèi)時(shí)間在等待上枪汪,降低了傳輸效率和無法知道需要重傳哪些數(shù)據(jù)包的問題涌穆。 快速重傳能解決超時(shí)重傳的等待時(shí)間太長的問題,但是對于究竟該重傳哪些包的問題仍然不能有效解決料饥。SACK能需要重傳哪些數(shù)據(jù)包的問題蒲犬,它可以知道哪些包是被確認(rèn)接收的,客戶端能據(jù)此判斷需要重傳的包岸啡。DSACK則是作為SACK的一個(gè)輔助措施原叮,可以用來判斷網(wǎng)絡(luò)究竟是出現(xiàn)了什么情況,據(jù)此做好網(wǎng)絡(luò)流量控制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奋隶,一起剝皮案震驚了整個(gè)濱河市擂送,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唯欣,老刑警劉巖嘹吨,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異境氢,居然都是意外死亡蟀拷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門萍聊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來问芬,“玉大人,你說我怎么就攤上這事寿桨〈诵疲” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵亭螟,是天一觀的道長挡鞍。 經(jīng)常有香客問我,道長预烙,這世上最難降的妖魔是什么墨微? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮默伍,結(jié)果婚禮上欢嘿,老公的妹妹穿的比我還像新娘。我一直安慰自己也糊,他們只是感情好炼蹦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狸剃,像睡著了一般掐隐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钞馁,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天虑省,我揣著相機(jī)與錄音,去河邊找鬼僧凰。 笑死探颈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的训措。 我是一名探鬼主播伪节,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼光羞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怀大?” 一聲冷哼從身側(cè)響起纱兑,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎化借,沒想到半個(gè)月后潜慎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蓖康,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年铐炫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒜焊。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驳遵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出山涡,到底是詐尸還是另有隱情,我是刑警寧澤唆迁,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布鸭丛,位于F島的核電站,受9級特大地震影響唐责,放射性物質(zhì)發(fā)生泄漏鳞溉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一鼠哥、第九天 我趴在偏房一處隱蔽的房頂上張望熟菲。 院中可真熱鬧,春花似錦朴恳、人聲如沸抄罕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呆贿。三九已至,卻和暖如春森渐,著一層夾襖步出監(jiān)牢的瞬間做入,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工同衣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竟块,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓耐齐,卻偏偏與公主長得像浪秘,于是被迫代替她去往敵國和親蒋情。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345