TCP 協議(滑動視窗——基礎)
相信大家都遇到過這樣的場景:
同學 Luffy 給你打電話,讓你記下一串手機號碼,可是你記憶力不太好,你跟 Luffy 約定,一次只最多隻能報 4 個數字,Luffy 念一遍,如果你聽到了就把他說的話重複一遍。接下來:
- 你:你一次最多報 4 個數字,多了我記不住啊!
- Luffy:139
- 你:139 (Luffy 知道你聽到了)
- Luffy:7548
- 你:7538 (很明顯你聽錯了)
- Luffy:不對,是7548
- 你:7548
- Luffy : 2669
- 你:2669
最後,你接收到的完整的號碼就是 139-7548-2669.
1. 滑動視窗
上面的場景,你一次最多隻能接受 4 個數字,表示你的滑動視窗大小就是 4. 在 TCP 協議中,也有這樣的滑動視窗,它的大小表示目前還能接收多少位元組的資料。
TCP 每次收到對方發來的報文,都會檢查視窗大小欄位,見圖 1.
圖1 TCP 首部中有一個欄位——16 位視窗大小
知道了對方的視窗大小後,就知道對方目前還能接收多少資料,接收的資料位元組序號是 TCP 段中的 ACK 的值到 ACK + 視窗大小,即 .
比如,你給對方傳送了一個段攜帶位元組序號為 [400, 500) 的資料。對方回送了一個 TCP 段,ack = 500, win = 100,就表示,我已經收到 [400, 500) 的資料我還能接收位元組序號為 [500, 600) 之間的資料,見圖 2。
圖2 滑動視窗
如果對方回送了一個 TCP 段,ack = 500, win = 0,就表示,我已經收到了 [400, 500) 的資料,但是我現在不能再接收資料了,你待會再發。
圖3 對方回送 0 大小的視窗,接收端的反應
2. 滑動視窗的目的
回顧本文開頭給出的打電話的例子,為什麼你要告訴對方一次最多隻能報 4 個數字?原因在於你的接受能力有限,不是說你無法記憶很多數字,只是在短期內,你記不住,你需要一段一段的記憶(一段一段的將資料放入緩衝區)。
所以,在 TCP 中,滑動視窗是為了實現流量控制。如果對方傳送資料過快,接收方就來不及接收(你來不急記住),接收方就需要通告對方,減慢資料的傳送(圖 3)。
需要特別注意的是,在學習滑動視窗的時候,我們假設網路無限好,不擁塞。只要你傳送了資料,對方一定可以收到。
再解釋一下網路擁塞的含義,它是指你傳送的資料滯留在網路中,遲遲未到達接收方。
3. 滑動視窗模擬
圖4 滑動視窗模擬
修正:圖4 中最後一個小圖修正一下文字,應該為『傳送方收到 ack=41, win=10, 知道對方希望接收序號為 [41, 51) 的資料』
- 傳送方接收到了對方發來的報文 ack = 33, win = 10,知道對方收到了 33 號前的資料,現在期望接收 [33, 43) 號資料。傳送方連續傳送了 4 個報文段假設為 A, B, C, D, 分別攜帶 [33, 35), [35, 36), [36, 38), [38, 41) 號資料。
- 接收方接收到了報文段 A, C,但是沒收到 B 和 D,也就是隻收到了 [33, 35) 和 [36, 38) 號資料。接收方傳送回對報文段 A 的確認:ack = 35, win = 10。
- 傳送方收到了 ack = 35, win = 10,對方期望接收 [35, 45) 號資料。接著傳送了一個報文段 E,它攜帶了 [41, 44) 號資料。
- 接收方接收到了報文段 B: [35, 36), D:[38, 41),接收方傳送對 D 的確認:ack = 41, win = 10. (這是一個累積確認)
- 傳送方收到了 ack = 41, win = 10,對方期望接收 [41, 51) 號資料。
- ……
需要注意的是,接收方接收 tcp 報文的順序是不確定的,並非是一定先收到 35 再收到 36,也可能是先收到 36,37,再收到 35.
4. 總結
- 理解滑動視窗的工作過程
- 滑動視窗的目的是什麼?