目錄
- TCP如何實(shí)現(xiàn)可靠傳輸?
- TCP如何實(shí)現(xiàn)流量控制?(滑動(dòng)窗口)
- TCP如何實(shí)現(xiàn)擁塞控制坟乾?(慢開始迹辐、擁塞避免、快重傳甚侣、快恢復(fù))
引申:
1.UDP能否也實(shí)現(xiàn)可靠傳輸明吩?
2.TCP為什么要三次握手、四次揮手殷费?兩次握手印荔、3次揮手行不行?
3.什么情況使用UDP好详羡、什么情況使用TCP好仍律?
1. TCP如何實(shí)現(xiàn)可靠傳輸
TCP的可靠傳輸是基于連續(xù)ARQ協(xié)議的,ARQ協(xié)議中有兩個(gè)重要的概念:滑動(dòng)窗口和累計(jì)確認(rèn)实柠。但是我認(rèn)為TCP能實(shí)現(xiàn)可靠傳輸不僅僅是靠連續(xù)ARQ協(xié)議水泉,還依靠了:
1.通過三次握手、四次揮手來保證信道的可連接性 主到;
2.采用停止等待協(xié)議茶行、連續(xù)ARQ協(xié)議(自動(dòng)重傳)來保證數(shù)據(jù)的正確性;
3.序列號和確認(rèn)應(yīng)答號保證了數(shù)據(jù)的有序性登钥,
4.校驗(yàn)和:如果收到字節(jié)的檢驗(yàn)和有差錯(cuò)畔师,TCP 將丟棄這個(gè)報(bào)文段和不確認(rèn)收到此報(bào)文段。
1.1 TCP三次握手的必要性
TCP通過三次握手來確定這是一個(gè)可靠的連接牧牢,三次握手的目的是為了確定客戶端和服務(wù)端都有正常的【收發(fā)】能力看锉,即客戶端可以發(fā)送和接收消息,服務(wù)器也可以發(fā)送和接收消息塔鳍。
- 第一次:客戶端 → 發(fā)送請求 ( SYN = 1伯铣,syn = x )→ 服務(wù)端,服務(wù)端知道【客戶端】可以【發(fā)送】消息轮纫;
- 第二次:服務(wù)端 → 應(yīng)答+請求 ( ACK = 1 , SYN = 1腔寡,syn = y , ack = x + 1)→ 服務(wù)端,客戶端知道【服務(wù)端】可以【接收】自己的消息掌唾,并且知道它能【發(fā)送】消息放前;
- 第三次:客戶端 → 應(yīng)答 ( ACK = 1,syn = x + 1 , ack = y + 1 )→ 服務(wù)端糯彬,服務(wù)端也確認(rèn)【客戶端】能【接收】消息凭语。
那么如果只有兩次握手,則【客戶端】的【接收】能力并沒有得到確認(rèn)撩扒,不能確定這是一個(gè)可靠的連接似扔。同時(shí),為了實(shí)現(xiàn)可靠數(shù)據(jù)傳輸, TCP 協(xié)議的通信雙方炒辉, 都必須維護(hù)一個(gè)序列號豪墅, 以標(biāo)識(shí)發(fā)送出去的數(shù)據(jù)包中, 哪些是已經(jīng)被對方收到的辆脸。 三次握手的過程即是通信雙方相互告知序列號起始值但校, 并確認(rèn)對方已經(jīng)收到了序列號起始值的必經(jīng)步驟,如果只是兩次握手啡氢, 至多只有連接發(fā)起方的起始序列號能被確認(rèn), 另一方選擇的序列號則得不到確認(rèn)术裸。
1.2 TCP為什么要4次揮手倘是?
- 因?yàn)門CP是一個(gè)全雙工的鏈接,即客戶端可以向服務(wù)器傳送數(shù)據(jù)袭艺,服務(wù)器也可以向客戶端傳送數(shù)據(jù)搀崭。當(dāng)客戶端【請求】斷開連接時(shí),代表客戶端需要向服務(wù)器發(fā)送的數(shù)據(jù)已經(jīng)完畢猾编,服務(wù)器【確認(rèn)】收到斷開連接瘤睹,此時(shí)進(jìn)行了兩次揮手。 如果和建立TCP鏈接時(shí)一樣立刻進(jìn)行第三次揮手會(huì)出現(xiàn)一個(gè)問題:服務(wù)器需要向客戶端發(fā)送的數(shù)據(jù)此時(shí)不一定全部發(fā)送完畢答倡,這時(shí)需要等待服務(wù)器發(fā)送完送有的數(shù)據(jù)轰传,才能進(jìn)行下面的操作。
- 當(dāng)服務(wù)器也發(fā)送完所有的數(shù)據(jù)給客戶端瘪撇,才能進(jìn)行后兩次揮手获茬。服務(wù)器向客戶端發(fā)送一條斷開連接的【請求】,客戶端【確認(rèn)】應(yīng)答后倔既,服務(wù)器立刻進(jìn)入了CLOSED模式恕曲。
- 此時(shí)客戶端還不能立刻進(jìn)入CLOSED模式,需要等待2MSL渤涌。原因:由于客戶端最后一個(gè)ACK可能會(huì)丟失佩谣,這樣B就無法正常進(jìn)入CLOSED狀態(tài)。于是B會(huì)重傳請求釋放的報(bào)文实蓬,而此時(shí)A如果已經(jīng)關(guān)閉了茸俭,那就收不到B的重傳請求,就會(huì)導(dǎo)致B不能正常釋放瞳秽。而如果A還在等待時(shí)間內(nèi)瓣履,就會(huì)收到B的重傳,然后進(jìn)行應(yīng)答练俐,這樣B就可以進(jìn)入CLOSED狀態(tài)了袖迎。
1.3 停止等待協(xié)議、連續(xù)ARQ協(xié)議、選擇重傳
這三個(gè)協(xié)議的目的燕锥,都是為了保證了客戶端和服務(wù)器的數(shù)據(jù)辜贵,能確保傳送到對面。如果數(shù)據(jù)在中途丟失或者延遲归形,則需要重新發(fā)送托慨,一直到對面接收到為止。
停止等待協(xié)議:
A每發(fā)送完一個(gè)報(bào)文M暇榴,就等候B對其確認(rèn)厚棵;如果沒收到確認(rèn),則不能繼續(xù)發(fā)送蔼紧,收到確認(rèn)后再繼續(xù)發(fā)送婆硬。缺點(diǎn)是一個(gè)個(gè)字節(jié)發(fā)送效率太低。
數(shù)組分組在傳輸過程中發(fā)生錯(cuò)誤時(shí)有兩種情況:
1奸例、當(dāng)接收方收到錯(cuò)誤數(shù)據(jù)分組時(shí)彬犯,會(huì)直接丟棄分組。
2查吊、如果數(shù)組分組在傳輸?shù)倪^程中丟失谐区。
在這兩種情況下,接收方都不會(huì)發(fā)送任何信息逻卖。發(fā)送方在一定時(shí)間內(nèi)沒有收到確認(rèn)宋列,就認(rèn)為分組丟失,然后重傳該數(shù)據(jù)分組箭阶,這就叫超時(shí)重傳虚茶。
停止等待ARQ協(xié)議就是通過這種確認(rèn)和重傳的機(jī)制,在不可靠的網(wǎng)絡(luò)上實(shí)現(xiàn)可靠通信仇参。
連續(xù)ARQ協(xié)議:
顯然嘹叫,每次只發(fā)送一個(gè)報(bào)文然后等待確認(rèn)效率太低。連續(xù) ARQ 協(xié)議可提高信道利用率诈乒。發(fā)送方維持一個(gè)發(fā)送窗口罩扇,凡位于發(fā)送窗口內(nèi)的分組可以連續(xù)發(fā)送出去,而不需要等待對方確認(rèn)怕磨。接收方一般采用累計(jì)確認(rèn)喂饥,對按序到達(dá)的最后一個(gè)分組發(fā)送確認(rèn),表明到這個(gè)分組為止的所有分組都已經(jīng)正確收到了肠鲫。如果中間發(fā)生丟失包的情況员帮,A需要回退到確認(rèn)的報(bào)文重新發(fā)送。
A的發(fā)送窗口大小是根據(jù)B接受窗口設(shè)置的导饲。也就是說A發(fā)送的報(bào)文速度不能超過B處理報(bào)文的速度捞高。
TCP中對于超時(shí)重傳時(shí)間的選擇是根據(jù)平均往返時(shí)間RTT來計(jì)算的氯材。也就是說,如果A超過一個(gè)報(bào)文平均往返時(shí)間沒有收到確認(rèn)硝岗,就會(huì)重新發(fā)送報(bào)文氢哮。
選擇重傳:
選擇重傳ARQ協(xié)議是指在接收方收到未按序排列的數(shù)據(jù)流時(shí),通知發(fā)送方重傳缺失的數(shù)據(jù)型檀,而不是重傳全部數(shù)據(jù)冗尤。TCP數(shù)據(jù)段首部中添加選擇確認(rèn)選項(xiàng)SACK可以實(shí)現(xiàn)該目的。
如圖所示胀溺,假設(shè)上述分組都在發(fā)送窗口中裂七,收到三個(gè)不連續(xù)的分組。三個(gè)分組的邊界分別為:[4000,5001]月幌、[6000,7001]碍讯、[8000,9001]。在建立TCP連接時(shí)扯躺,連接雙方先商定好,在首部選項(xiàng)中加入“允許SACK”的選項(xiàng)蝎困。在之后的TCP報(bào)文段中增加SACk選項(xiàng)录语,以便接收方向發(fā)送方報(bào)告不連續(xù)的字節(jié)塊的邊界。
因?yàn)樾蛱柺?2位禾乘,因此指明一個(gè)邊界需要4個(gè)字節(jié)澎埠,說明一個(gè)字節(jié)塊的邊界需要8個(gè)字節(jié)。另外需要一個(gè)字節(jié)指明是SACK選項(xiàng)始藕,一個(gè)字節(jié)指明這個(gè)選項(xiàng)的大小蒲稳。TCP報(bào)文段首部選項(xiàng)最大為40個(gè)字節(jié),因此最多指明4個(gè)字節(jié)塊的邊界信息伍派。
TCP標(biāo)準(zhǔn)并未指明發(fā)送方應(yīng)該如何響應(yīng)SACK江耀,因此大多數(shù)實(shí)現(xiàn)還是重傳所有未被確認(rèn)的數(shù)據(jù)分組。
2. TCP的流量控制
利用滑動(dòng)窗口機(jī)制可以實(shí)現(xiàn)對發(fā)送方的流量控制诉植。在TCP連接建立時(shí)祥国,接收方會(huì)在確認(rèn)報(bào)文段中給出自己接收窗口的大小。在每次發(fā)送確認(rèn)報(bào)文時(shí)能夠根據(jù)情況動(dòng)態(tài)調(diào)整接收窗口的大小晾腔,并將告知發(fā)送方舌稀。如下圖所示:
??發(fā)送方發(fā)送序號從1開始的100字節(jié)的數(shù)據(jù),接收方在確認(rèn)報(bào)文中聲明自身的接收窗口大小為300字節(jié)灼擂。之后發(fā)送方發(fā)送300字節(jié)數(shù)據(jù)壁查,接收方在確認(rèn)報(bào)文中聲明自身接收窗口大小調(diào)整為50字節(jié)。發(fā)送方再發(fā)送50字節(jié)數(shù)據(jù)之后剔应,收到接收方傳來的確認(rèn)報(bào)文睡腿,在該報(bào)文中聲明接收窗口為0语御。
??在接收方接收窗口為0時(shí),發(fā)送方不再發(fā)送數(shù)據(jù)嫉到,直到接收方發(fā)送確認(rèn)報(bào)文表明窗口大小發(fā)生改變沃暗。可是這個(gè)確認(rèn)報(bào)文不一定能夠被發(fā)送方接收到何恶,如果一旦該確認(rèn)報(bào)文丟失孽锥,雙方都將處于等待中,形成死鎖细层。為防止這種情況出現(xiàn)惜辑,TCP規(guī)定在收到對方接受窗口為0時(shí),啟動(dòng)一個(gè)堅(jiān)持定時(shí)器周期性的發(fā)送探測報(bào)文疫赎,以確定對方接收窗口為0的狀態(tài)是否改變盛撑。
??另外,TCP標(biāo)準(zhǔn)規(guī)定:接收方接收窗口為0時(shí)捧搞,不再接收正常數(shù)據(jù)抵卫,但是可以接收零窗口探測報(bào)文段、確認(rèn)報(bào)文段胎撇、攜帶緊急數(shù)據(jù)的報(bào)文段介粘。
3. TCP的擁塞控制
- 擁塞控制是指防止過多的數(shù)據(jù)注入網(wǎng)絡(luò)中,這樣可以使網(wǎng)絡(luò)中路由器或者鏈路不致過載⊥硎鳎現(xiàn)在通信線路的傳輸質(zhì)量一般都很好姻采,因傳輸出現(xiàn)差錯(cuò)丟棄分組的概率很小。因此爵憎,判斷網(wǎng)絡(luò)擁塞的依據(jù)就是出現(xiàn)了超時(shí)慨亲。
- TCP進(jìn)行擁塞控制常用的算法有四種:慢啟動(dòng)、擁塞避免宝鼓、快重傳刑棵、快恢復(fù)。
3.1 慢啟動(dòng)
當(dāng)主機(jī)開始發(fā)送數(shù)據(jù)時(shí)席函,如果立即將較大的發(fā)送窗口的全部數(shù)據(jù)注入網(wǎng)路中铐望,那么由于不清楚網(wǎng)絡(luò)的情況,有可能引起擁塞茂附。比較好的方式是試探一下正蛙,即從小到大逐漸增大發(fā)送端的擁塞控制窗口數(shù)值。cwnd以指數(shù)增長的形式增長营曼。
3.2 擁塞避免
- 當(dāng)窗口值逐漸增大時(shí)乒验,為了防止cwnd的增長導(dǎo)致網(wǎng)絡(luò)擁塞,還需要一個(gè)變量——慢開始門限ssthresh蒂阱。當(dāng)cwnd以指數(shù)增長的形式增長到大于或等于ssthresh時(shí)锻全,就不再采用慢啟動(dòng)算法狂塘,而是采用擁塞避免算法來進(jìn)行擁塞控制。
- 擁塞避免算法規(guī)定:每次收到一個(gè)確認(rèn)時(shí)將cwnd增加1/cwnd個(gè)SMSS鳄厌。即不再是像慢啟動(dòng)算法那樣經(jīng)過一輪傳輸cwnd翻倍了荞胡,而是經(jīng)過一輪傳輸增加一個(gè)SMSS。這是一種加性增長的關(guān)系了嚎。
??當(dāng)擁塞發(fā)生時(shí)(超時(shí)或收到重復(fù)確認(rèn))泪漂,cwnd被設(shè)置為1個(gè)SMSS。ssthresh被設(shè)置為當(dāng)前窗口大小的一半歪泳,但最少為 2個(gè)報(bào)文段萝勤。
3.3 快重傳
- 如果個(gè)別報(bào)文段在網(wǎng)絡(luò)中丟失,網(wǎng)絡(luò)并沒有發(fā)生擁塞呐伞,這種情況下發(fā)送方收不到確認(rèn)報(bào)文敌卓,在超時(shí)之后會(huì)重傳該報(bào)文。發(fā)送方誤以為網(wǎng)絡(luò)發(fā)生擁塞伶氢,錯(cuò)誤的啟動(dòng)慢開始算法趟径,降低了傳輸效率。
- 采用快重傳算法可以讓發(fā)送方盡早知道個(gè)別報(bào)文段的丟失癣防《婺ǎ快重傳算法要求接收方不要延時(shí)發(fā)送確認(rèn),即使收到失序的報(bào)文段也要立刻發(fā)送對已收到報(bào)文的重復(fù)確認(rèn)劣砍。如下圖所示:
接收方收到M1之后發(fā)送對M1的確認(rèn)報(bào)文,M2報(bào)文丟失扇救,之后接收方收到M3刑枝、M4、M5時(shí)每次都發(fā)送對M1報(bào)文的重復(fù)確認(rèn)迅腔∽俺快重傳算法規(guī)定當(dāng)收到三次重復(fù)確認(rèn)后沧烈,發(fā)送方就認(rèn)為M2報(bào)文段丟失掠兄,立即重傳M2報(bào)文段。
- 快重傳算法并非取消了重傳機(jī)制锌雀,只是在某些情況下更早的重傳丟失的報(bào)文段(如果當(dāng)發(fā)送端接收到三個(gè)重復(fù)的確認(rèn)ACK時(shí)蚂夕,則斷定分組丟失,立即重傳丟失的報(bào)文段腋逆,而不必等待重傳計(jì)時(shí)器超時(shí))婿牍。
3.4 快恢復(fù)
- 當(dāng)發(fā)送方連續(xù)收到接收方發(fā)來的三個(gè)重復(fù)確認(rèn)時(shí),就執(zhí)行“乘法減小”算法惩歉,把慢開始門限減半等脂,這是為了預(yù)防網(wǎng)絡(luò)發(fā)生擁塞俏蛮。
- 由于發(fā)送方現(xiàn)在認(rèn)為網(wǎng)絡(luò)很可能沒有發(fā)生擁塞,因此現(xiàn)在不執(zhí)行慢開始算法上遥,而是把cwnd(擁塞窗口)值設(shè)置為慢開始門限減半后的值搏屑,然后開始執(zhí)行擁塞避免算法,使擁塞窗口的線性增大粉楚。
作者:白馬笑西風(fēng)
鏈接:https://juejin.cn/post/6844903799253909512