TCP協議(2)

上一章說到 TCP 的緩存機制,這一回接著往下講

流量控制

首先,要明確流量控制是針對誰而言的。之前說過發送方會維護有一個發送窗口 (rwnd, receiver window),落在這個發送窗口的數據都可以發送出去,但是可能存在一種情況:發送方發送數據的速度太快,接收方應用層的應用處理數據太慢,導致接收方接收緩存的空間已經滿了,那么如果這個時候發送方還可以不斷的向發送方發送數據,那么這些數據將沒有地方安放。流量控制的目的就是為了控制發送方發送數據的速度。

從上面滑動窗口的執行表現可以看出,只要控制滑動窗口的大小那么就可以控制發送方發送數據的速度。原因很明顯,滑動窗口越小,那么發送方可以發送的數據大小越小。在實際的通信過程中,接收方會告訴發送方自己的接收窗口大小,(這點在 TCP 報文首部中有所體現,之后會再次看到)發送方根據接收方傳來的窗口值來設定自己的發送閾值。

這里假設一個情況,當接收方B告訴發送方A自己的接收窗口已經變成 0,那么 A 收到這個消息之后就不再發送數據給 B 直到接收方 B 重新發送一個窗口值給 A。那么假設 B 在重新發送窗口值的過程中該報文丟失在網絡中,那么造成 A 收不到該報文,B 以為自己報文已經發送給 A 了。這種情況下就會造成死鎖的局面。為了打破這種死鎖的現象,TCP 設計了一個持續計時器的東西,只要任意一方收到對方發來的窗口大小為 0 通知,那么馬上啟動這個持續計時器,當持續計時器時間到期還沒收到對方的報文,那么就會發送一個稱之為探測報文的數據來探測對方是否真的不能接收數據了。

擁塞控制

在對擁塞控制進行討論之前,我們需要明白為什么要有擁塞控制以及擁塞控制和流量控制的區別。這兩個問題可以放在一起分析

流量控制是為了避免發送方發送數據過快導致接收方來不及處理數據,在討論流量控制的時候我們忽略了一個前提:網絡環境。通信雙方不單單要考慮到接收方是否來得及處理這些數據,在發送的時候還要考慮網絡環境是否可以承載這么大的數據。如果網絡環境出現了擁塞,那么就應該有一定的機制來保證在惡劣的網絡環境下還可以進行通信以及不加重網絡的擁塞程度。

在討論擁塞控制的時候,我們應該忽略流量控制,也就是假設通信雙方可以及時的處理數據,這樣子不會增加擁塞控制的復雜度。

目前擁塞控制有4種算法:

  • 慢開始
  • 擁塞避免
  • 快重傳
  • 快恢復

這四種算法并不是單獨使用的,而是配合使用。具體算法實現分析如下。

通信雙方維護一個叫做擁塞窗口 (cwnd, congesion window) 的值,這個值取決于網絡中的擁塞率,發送方的發送窗口的值就等于擁塞窗口的大小(注意,如上面所說的這里忽略了流量控制,實際中還需要考慮到流量控制),只要網絡中沒有出現擁塞,那么擁塞窗口的值就可以增大一些,這就意味著發送方可以發送到網絡中的數據就越多。只要網絡出現擁塞,那么擁塞窗口的值就小一點,減少主機發送數據的大小以避免加劇網絡的擁塞率。

上面的方式很好理解,但是問題在于主機如何判斷當前網絡是否擁塞?到這里我們知道,當網絡發生擁塞時,網絡中的某一個路由器節點就會丟棄數據。那么當發送方沒有收到接收方發來的確認報文就認為網絡中可能出現了擁塞。

下面分析一下這四種算法的實現邏輯

慢開始

當主機開始發送數據的時候,cwnd 的值是比較小的,這樣子就避免了在不知道網絡擁塞率的情況下注入大量的數據到網絡中。

  • 第一次,發送主機每次只發送小于等于 cwnd 大小的數據,當收到接收方的確認報文之后,就把 cwnd 的值翻倍
  • 當第二次發送數據發送方就可以發送小于等于 2*cwnd 大小,在發送方接收到接收方發來的確認報文之后將 cwnd 的值再次翻倍。

以此類推。從上面的流程中可以看出慢開始名字的含義體現在其執行表現上是開始起點低,但是其增長速度是指數級的。

擁塞避免

擁塞避免和慢開始很像,只是對于擁塞避免算法而言,其 cwnd 的增長是以 +1 的方式,而不是翻倍。也就是說當第 4 次發送數據的時候,慢開始可以發送最多 8cwnd 的數據,而擁塞避免只能發送 4cwnd 的數據。很明顯,擁塞避免的 cwnd 的增長速度為線性的。

為了避免 cwnd 的增長導致網絡擁塞,還需要設置一個慢開始門限的值,作用如下

  • 當 cwnd 小于慢開始門限,使用慢開始算法
  • 當 cwnd 大于慢開始門限,改用擁塞避免算法
  • 當 cwnd 等于慢開始門限,兩者都可以使用。

在 擁塞窗口大于慢開始門限 之后切換為擁塞避免的原因很簡單,慢開始的增長率太快,在接下來很容易就導致網絡擁塞,所以改用避免擁塞的方式來避免 cwnd 增長過快。

當網絡出現擁塞的情況下,不管是使用慢開始還是避免擁塞算法,都要執行如下的操作:

  • 把慢開始門限的值降為原來的一半
  • cwnd 的值重新置為 1 個單位,執行慢開始算法。

快重傳

在慢開始中我們知道,主機判斷在超時時間之內沒有收到接收方發送的確認報文就認為出現了擁塞,這個時候開始降低慢開始門限和重置cwnd的值。但是當使用快重傳的算法之后,思路就變了。

假設發送方 A 發送 [1,7] 序號的報文:P1,P2 都已經被接收方 B 接收并且發出了確認,這個時候 B 收到 P4 報文,按照上一篇講的連續 ARQ 協議中的說明,這個時候 B 不能發送對 P4 的確認,它可以什么都不做,但是按照快重傳的算法規定,這個時候 B 必須再次發送對 P2 的重復確認。這樣子是為了讓 A 知道報文 P3 沒有到達接收方。假設接下來 B 仍然沒有收到 P3,而是收到了 P5,P6 報文,那么 B 仍然要重新發送 P2 的確認。這樣子接收方 A 一共收到了 4 次對 P2 報文的確認,其中有 3 次是重復確認。快重傳規定當發送方收到對同一個報文的 3 次重復確認就應該立即重傳對方尚未接收到的字段。在這個例子中A應該重新發送報文 P3。

快恢復

同樣,快重傳情況下如果出現了網絡擁塞,也需要一個機制來降低主機注入到網絡中的數據量,這里就使用快恢復算法。快恢復算法執行表現如下:

  • 當發送方接收到三個重復確認,就把慢開始門限減半,同時把 cwnd 的值改為慢開始門限的一半。
  • 不執行慢開始算法,而是執行避免擁塞算法。

比較兩組對于網絡擁塞的處理可以發現快重傳更多是為了避免擁塞,回顧快重傳中的邏輯其實可以看出當時網絡并不一定發生了擁塞,因為如果網絡擁塞就不會有好幾個報文會到達接收方。所以,快恢復中只是把 cwnd 降為慢開始門限的一半來防止過大的 cwnd 可能導致未來擁塞。

接下來,我們考慮接收方接收緩存的限制,即同時考慮擁塞控制和流量控制。可以得出一個式子

發送方窗口的最大值 = Min(rwnd, cwnd);

TCP 報文

很多人在學習 TCP 報文的時候直接看報文信息是有點不合理的,因為對于 TCP 報文為何被設計成現在的樣子沒有一個清楚的認識,只是單純記住其含義是沒用的,應該理解 TCP 其工作的流程之后再回顧 TCP 報文含義就很明顯了。

TCP-Header

如上圖就是 TCP 報頭的數據內容。這里挑出一些做解釋

  • Window size(窗口大小)。 這里的窗口大小就是流量控制和擁塞控制中所提到用來限制發送方發送數據的速率
  • PSH 6 個標志位中的一位。根據上面講的,通常應用層的數據到達TCP層都會進入發送緩存等待若干時間再發送。如果 PSH=1 那么這個數據報會被馬上發送給對方,而不是進入發送緩存等待。同理對于接收數據也不會進入接收緩存而是直接交付給上層應用。

好了,關于TCP的理論知識點就到這里,雖然沒有對header信息進行充分的說明。甚至連三次握手連接,四次握手斷開都沒有說明。但是如果理解了上面TCP工作的流程。對于header信息以及握手協議應該很容易就掌握。

本文首發于:https://jaychen.cc
作者:jaychen

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容