一、為什么TCP是可靠傳輸?
1. 停止等待協(xié)議
通過確認(rèn)與超時(shí)重傳機(jī)制實(shí)現(xiàn)可靠傳輸
在發(fā)送完一個(gè)分組后,必須暫時(shí)保留已發(fā)送的分組的副本。
分組和確認(rèn)分組都必須進(jìn)行編號。
超時(shí)計(jì)時(shí)器的重傳時(shí)間應(yīng)當(dāng)比數(shù)據(jù)在分組傳輸?shù)钠骄禃r(shí)間更長一些。
出現(xiàn)差錯(cuò)或丟失的時(shí)候,發(fā)送方會將自己備份的副本再重傳一次,直到收到接收的確認(rèn)信息。當(dāng)接收方收到重復(fù)的數(shù)據(jù)時(shí),會直接丟棄,但是會給發(fā)送方請確認(rèn)自己已經(jīng)收到了。
2. 改進(jìn)的停止等待協(xié)議——連續(xù)ARQ協(xié)議和滑動窗口協(xié)議
上面的停止等待協(xié)議每發(fā)送一組數(shù)據(jù)就必須等到接收方回復(fù)確認(rèn)后,再發(fā)起第二組數(shù)據(jù),如果出現(xiàn)超時(shí)重傳的話,效率更低。因此為了提高傳輸?shù)男?,改進(jìn)了等待傳輸協(xié)議。
連續(xù)ARQ協(xié)議和滑動窗口協(xié)議的機(jī)制是以接收方回復(fù)確認(rèn)為單位,每次連續(xù)發(fā)送一個(gè)滑動窗口指定的數(shù)據(jù)組。示例圖如下:
2.1 什么是滑動窗口協(xié)議?(發(fā)送方怎么發(fā)送數(shù)據(jù))
滑動窗口是由發(fā)送方維護(hù)的類似指針的變量,在每收到一個(gè)接收方的確認(rèn)消息后,該指針向前移動并發(fā)送數(shù)據(jù),到窗口指定大小的數(shù)據(jù)組時(shí)停下,等待接收方的確認(rèn)。示意看圖:
2.2 接收方怎么回復(fù)確認(rèn)?
累積確認(rèn)機(jī)制
發(fā)送方不對收到的分組逐個(gè)發(fā)送確認(rèn),而是對按序到達(dá)的最后一個(gè)分組發(fā)送確認(rèn),這樣就表示:到這個(gè)分組為止的所有分組都已正確收到了。
優(yōu)點(diǎn):容易實(shí)現(xiàn),即使確認(rèn)丟失也不必重傳。
缺點(diǎn):不能向發(fā)送方反映出接收方已經(jīng)正確收到的所有分組的信息。
Go-back-N(回退 N)
為了解決上述同一窗口中數(shù)據(jù)組不能完整確認(rèn)的問題,連續(xù)ARQ協(xié)議采用了回退機(jī)制。比如說:發(fā)送方發(fā)送了前 5 個(gè)分組,而中間的第 3 個(gè)分組丟失了。這時(shí)接收方只能對前兩個(gè)分組發(fā)出確認(rèn)。發(fā)送方無法知道后面三個(gè)分組的下落,而只好把后面的三個(gè)分組都再重傳一次。這就叫做 Go-back-N(回退 N),表示需要再退回來重傳已發(fā)送過的 N 個(gè)分組。
結(jié)論:當(dāng)通信線路質(zhì)量不好時(shí),連續(xù) ARQ 協(xié)議會帶來負(fù)面的影響。可能還不如傳統(tǒng)的停止等待協(xié)議。
3. TCP可靠傳輸?shù)膶?shí)現(xiàn)
TCP 連接的每一端都必須設(shè)有兩個(gè)窗口——一個(gè)發(fā)送窗口和一個(gè)接收窗口。
TCP 的可靠傳輸機(jī)制用字節(jié)的序號進(jìn)行控制。TCP 所有的確認(rèn)都是基于序號而不是基于報(bào)文段。
TCP 兩端的四個(gè)窗口經(jīng)常處于動態(tài)變化之中。
TCP連接的往返時(shí)間 RTT 也不是固定不變的。需要使用特定的算法估算較為合理的重傳時(shí)間。
3.1 以字節(jié)為單位的滑動窗口技術(shù)
滑動窗口是面向字節(jié)流的,為了方便記住每個(gè)分組的序號,下面的圖解以一個(gè)分組假設(shè)100個(gè)字節(jié),為了方便畫圖表示,將分組進(jìn)行編號簡化表示,如圖所示,但是要記住,每一個(gè)分組的序號是多少。
3.2 改進(jìn)的確認(rèn)——選擇確認(rèn)(SACK)
TCP通信時(shí),如果發(fā)送序列中間某個(gè)數(shù)據(jù)包丟失,TCP會通過重傳最后確認(rèn)的分組后續(xù)的分組,這樣原先已經(jīng)正確傳輸?shù)姆纸M也可能重復(fù)發(fā)送,降低了TCP性能。SACK(Selective Acknowledgment,選擇確認(rèn))技術(shù),使TCP只重新發(fā)送丟失的包,不用發(fā)送后續(xù)所有的分組,而且提供相應(yīng)機(jī)制使接收方能告訴發(fā)送方哪些數(shù)據(jù)丟失,哪些數(shù)據(jù)已經(jīng)提前收到等。在建立 TCP 連接時(shí),就要在 TCP 首部的選項(xiàng)中加上“允許 SACK”的選項(xiàng),而雙方必須都事先商定好。原來首部中的“確認(rèn)號字段”的用法仍然不變。只是以后在 TCP 報(bào)文段的首部中都增加了 SACK 選項(xiàng),以便報(bào)告收到的不連續(xù)的字節(jié)塊的邊界。
選擇性確認(rèn)最多表示4個(gè)邊界:由于首部選項(xiàng)的長度最多只有 40 字節(jié)。需要一個(gè)字節(jié)指明是SACK選項(xiàng),另一個(gè)字節(jié)指明占多少字節(jié)。而指明一個(gè)邊界就要用掉 4 字節(jié)。在選項(xiàng)中最多只能指明 4 個(gè)字節(jié)塊的邊界信息。因4個(gè)字節(jié)塊共8個(gè)邊界信息。
抓包分析:
3.3 超時(shí)重傳時(shí)間的選擇?
重傳機(jī)制是 TCP 中最重要和最復(fù)雜的問題之一。TCP 每發(fā)送一個(gè)報(bào)文段,就對這個(gè)報(bào)文段設(shè)置一次計(jì)時(shí)器。只要計(jì)時(shí)器設(shè)置的重傳時(shí)間到但還沒有收到確認(rèn),就要重傳這一報(bào)文段。那么這個(gè)重傳時(shí)間到底應(yīng)該設(shè)置多少呢?這里面有學(xué)問。以下是我截取的“手抄報(bào)”,暫時(shí)看不懂。建議跳過。
加權(quán)平均往返時(shí)間
TCP 保留了 RTT 的一個(gè)加權(quán)平均往返時(shí)間 RTTS(這又稱為平滑的往返時(shí)間)。第一次測量到 RTT 樣本時(shí),RTTS 值就取為所測量到的 RTT 樣本值。以后每測量到一個(gè)新的 RTT 樣本,就按下式重新計(jì)算一次 RTTS:
超時(shí)計(jì)時(shí)器設(shè)置的超時(shí)重傳時(shí)間RTO
往返時(shí)間的測量
Karn算法
二、TCP的流量控制
流量控制(flow control)就是讓發(fā)送方的發(fā)送速率不要太快,既要讓接收方來得及接收,也不要使網(wǎng)絡(luò)發(fā)生擁塞。利用滑動窗口機(jī)制可以很方便地在 TCP 連接上實(shí)現(xiàn)流量控制。?
流量控制舉例說明:
零窗口處理——持續(xù)計(jì)數(shù)器
考慮上面的例子中,當(dāng)A發(fā)送的數(shù)據(jù)已經(jīng)到達(dá)B的接收窗口上限,此時(shí)A就必須等待B處理了部分?jǐn)?shù)據(jù)后,待接收窗口有空閑的時(shí)候,再次發(fā)送數(shù)據(jù),那么A是怎么知道B的接收窗口何時(shí)有空閑呢?這時(shí)就用到了持續(xù)計(jì)時(shí)器。
TCP 為每一個(gè)連接設(shè)有一個(gè)持續(xù)計(jì)時(shí)器。只要 TCP 連接的一方收到對方的零窗口通知,就啟動持續(xù)計(jì)時(shí)器。若持續(xù)計(jì)時(shí)器設(shè)置的時(shí)間到期,就發(fā)送一個(gè)零窗口探測報(bào)文段(僅攜帶 1 字節(jié)的數(shù)據(jù)),而對方就在確認(rèn)這個(gè)探測報(bào)文段時(shí)給出了現(xiàn)在的窗口值。若窗口仍然是零,則收到這個(gè)報(bào)文段的一方就重新設(shè)置持續(xù)計(jì)時(shí)器。若窗口不是零,則死鎖的僵局就可以打破了。
三、TCP的傳輸效率
關(guān)于TCP的傳輸效率問題,需要從三方面來考慮,1.何時(shí)發(fā)送;2.少字節(jié)發(fā)送數(shù)據(jù)問題;3.糊涂窗口綜合癥問題
3.1 TCP報(bào)文的發(fā)送時(shí)機(jī):
第一種機(jī)制是 TCP 維持一個(gè)變量,它等于最大報(bào)文段長度 MSS。只要緩存中存放的數(shù)據(jù)達(dá)到 MSS 字節(jié)時(shí),就組裝成一個(gè) TCP 報(bào)文段發(fā)送出去。
第二種機(jī)制是由發(fā)送方的應(yīng)用進(jìn)程指明要求發(fā)送報(bào)文段,即 TCP 支持的推送(push)操作。
第三種機(jī)制是發(fā)送方的一個(gè)計(jì)時(shí)器期限到了,這時(shí)就把當(dāng)前已有的緩存數(shù)據(jù)裝入報(bào)文段(但長度不能超過 MSS)發(fā)送出去。
3.2 少量字節(jié)發(fā)送數(shù)據(jù)問題:
問題描述:如果應(yīng)用程序一次產(chǎn)生一字節(jié)數(shù)據(jù),這樣會導(dǎo)致網(wǎng)絡(luò)由于太多的包而過載。如:從鍵盤輸入的一個(gè)字符,占用一個(gè)字節(jié),可能在傳輸上造成41字節(jié)的包,其中包括1字節(jié)的有用信息和40字節(jié)的標(biāo)題數(shù)據(jù)。
解決方案(NAGLE算法):發(fā)送端的應(yīng)用進(jìn)程將欲發(fā)送的數(shù)據(jù)逐個(gè)字節(jié)地送到TCP緩存,則發(fā)送端就將第一個(gè)字符先發(fā)送出去。將后面到達(dá)的字符都緩存起來。當(dāng)接收端收到對第一個(gè)字符確認(rèn)后,再將緩存中的所有字符裝成一個(gè)報(bào)文段發(fā)送出去,同時(shí)繼續(xù)對隨后到在的字符進(jìn)行緩存。只有在收到對前一個(gè)報(bào)文段確認(rèn)后才繼續(xù)發(fā)送下一個(gè)報(bào)文段。
3.3 糊涂窗口綜合癥問題:
問題描述:設(shè)想一種情況:接收端緩存已滿,而交互式的應(yīng)用進(jìn)程一次只從緩存中讀取一個(gè)字符,然后向發(fā)送端發(fā)送確認(rèn),并將窗口設(shè)置1個(gè)字節(jié)。接著發(fā)送端又發(fā)來1個(gè)字符。接收端發(fā)回確認(rèn),仍然將窗口設(shè)置為1個(gè)字節(jié)。這樣下去,網(wǎng)絡(luò)效率非常低。
解決方案:接收端等待一段時(shí)間,使得緩存已有足夠空間容納;或者緩存已有一半空的空間,再向發(fā)送端發(fā)送確認(rèn)。
編輯:hfy
評論
查看更多