目錄
流量控制
滑動窗口?
丟包重傳
情況一:數據到達,應答丟失
情況二:數據包丟失
流量控制
TCP協議會根據接收端的緩沖區大小來調整發送速度,剩余空間多則發送速度快,否則降低發送速度
接收端將??可以接收的緩沖區剩余空間??放? TCP ?部中的 "窗???" 字段,窗???字段越?, 說明?絡的吞吐量越?
接收端?旦發現??的緩沖區快滿了, 就會將窗???設置成?個更?的值通知給發送端
發送端接受到這個窗?之后, 就會減慢??的發送速度,如果接收端緩沖區滿了, 就會將窗?置為0; 這時發送?不再發送數據, 但是需要定期發送?個窗?探測數據段, 使接收端把窗???告訴發送端.
同時如果接收方的緩沖區騰出空間了,會發送窗口更新通知給發送端
窗口的初始大小由三次握手階段的ACK包來確定
窗口的大小在TCP首部里是16位,但并不意味著最大只能有65535,首部里的選項還包含了?個窗?擴?因?M, 實際窗???是 窗?字段的值左移 M 位
滑動窗口?
?對每?個發送的數據段, 都要給?個ACK確認應答. 收到ACK后再發送下?個數據段. 這樣做有?個?較?的缺點, 就是性能較差. 尤其是數據往返的時間較?的時候
既然如此,一次發送多條數據而不等待應答就可大大提升效率
如上圖,就是選擇一次發送四條數據(這里先記住,TCP協議只能像這樣一條發送有限字節的數據,圖中就是1000字節,也就是一次只能發送1000字節,不能更多,主要是因為數據鏈路層的限制,一次性只能傳輸有限字節的數據)
發送前四個段的時候, 不需要等待任何ACK, 直接發送
收到第?個ACK后, 滑動窗?向后移動, 繼續發送第五個段的數據,依次類推
操作系統內核為了維護這個滑動窗?, 需要開辟發送緩沖區來記錄當前還有哪些數據沒有應答; 只
有確認應答過的數據, 才能從緩沖區刪掉;
窗?越?, 則?絡的吞吐率就越?;?
所謂窗口,就是你寫算法題經常遇到的那個滑動窗口。。。這個窗口內所維護的就是待發送的數據段,窗口左邊是確認收到應答的數據段,窗口右邊就是以后再發的數據段
窗口大小的確定與TCP首部的16位窗口大小有關,先可以理解為那個字段就是窗口大小,根據上面流量控制的討論,我們知道,這個大小完全取決于接收端的緩沖區剩余空間大小,由這個參數,滑動窗口就能實現流量控制
窗口具體如何移動,取決于TCP首部的確認應答號
確認應答號i+1表示從1~i序號的數據段全收到了,比如上面的圖,如果2001~3000丟包了,只收到了1001~2000,不管后面的數據段接收端是否收到,確認應答號都是2001,注意窗口左邊的是已經確認過應答的數據段
根據確認應答號i,可以確定窗口左邊left = i;
根據16位窗口大小,確定窗口右邊right = left + window;
這樣滑動窗口就能向右移動起來,注意上面的計算方式只適用于沒有丟包的情況
丟包重傳
情況一:數據到達,應答丟失
這種情況下, 部分ACK丟了并不要緊, 因為可以通過后續的ACK進?確認,比如上圖1~1000的數據丟了無所謂,后續會收到1~2000的確認應答號2001,收到2001,根據確認應答好的定義,1~2000全收到了,不用管1~1000沒收到應答
情況二:數據包丟失
接收端根本沒收到數據包
?對于這種情況,拿下圖討論一下
窗口內的數據段都有可能丟,我們不妨先來回憶一下確認應答號的定義,確認應答號為i表示1~i-1的數據全部收到了,把left賦值為i,表示1~i-1的數據全收到了,如果i <= right,可以看出丟包了,那么i~right的每一個數據段,都有可能丟包了,但是,我們只需要處理最左邊的數據段,即以left為開頭的第一個數據段,把它重發即可
做完之后,如果確認應答號i > right,直接left = i, right = left + window,否則說明仍有丟包的,假設剛才發的以left為開始的第一個數據段為丟包,那么確認應答號i肯定大于left,直接left = i,然后完全重復上面的工作即可
實際中可能不能根據i <= right來判斷是否丟包,因為收到的確認應答號總是要更小的,以下圖為例
判斷是否丟包,一般根據是否收到3次重復的確認應答為準,不是兩次是因為,數據包到達時間并不嚴格按照發送先后時間,可能3001~4000比2001~3000先到達,導致收到了兩次重復的確認應答號,所以一般設置為3次,3次一般足夠精確,再多又不好了?