linux網絡編程之TCP定時器

TCP的四種定時器

  1. 重傳計時器:Retransmission Timer
  2. 堅持計時器:Persistent Timer
  3. 保活計時器:Keeplive Timer
  4. 時間等待計時器:Time_Wait Timer。

  • 重傳計時器
    爲了控制丟失的報文段或丟棄的報文段,也就是對報文段確認的等待時間。當TCP發送報文段時,就創建這個特定報文段的重傳計時器,可能發生兩種情況:若在計時器超時之前收到對報文段的確認,則撤銷計時器;若在收到對特定報文段的確認之前計時器超時,則重傳該報文,並把計時器復位;
    重傳時間=2*RTT;
    RTT的值應該動態計算。常用的公式是:RTT=previous RTT*i + (1-i)*current RTT。i的值通常取90%,即新的RTT是以前的RTT值的90%加上當前RTT值的10%.

Karn算法:對重傳報文,在計算新的RTT時,不考慮重傳報文的RTT。因爲無法推理出:發送端所收到的確認是對上一次報文段的確認還是對重傳報文段的確認。乾脆不計入。

  • 堅持計時器
    堅持定時器主要是解決零窗口大小通知可能導致的死鎖問題。剛開始接收端向發送端發送了一個零窗口報文段。在不久之後,如果接收端的緩存區有一定的空間可以接收數據,此時接收端就會向發送端發送了一個非零窗口大小的報文段(即窗口更新),但是這個非零窗口大小的報文段在傳輸過程中丟失,導致發送端無法接收到該非零窗口大小的報文段。因此,發送端就會一直處於等待非零窗口大小的報文端通知,由於接收端已經發送了非零窗口大小的報文段,而且並不知道該報文段在傳輸過程中丟失,則接收端會一直處於等待接收數據狀態,如果沒有任何措施的話,這個死鎖的局面會一直延續下去。
    爲了解決上面這個問題,TCP 爲每一個連接設有一個堅持定時器(也叫持續計數器)。當發送端收到零窗口的確認時,就啓動堅持計時器,當堅持計時器截止期到時,發送端就發送一個特殊的報文段,叫探測報文段,這個報文段只有一個字節的數據。探測報文段有序號,但序號永遠不需要確認,甚至在計算對其他部分數據的確認時這個序號也被忽略。探測報文段提醒接收端,確認已丟失,必須重傳。
    堅持計時器的截止期設置爲重傳時間的值,但若沒有收到來自接收端的響應,則發送另一個探測報文段,並將堅持計時器的值加倍和並復位,發送端繼續發送探測報文段,將堅持計時器的值加倍和復位,直到這個值增大到閾值爲止(通常爲 60 秒)。在此之後,發送端每隔 60s 就發送一個報文段,直到窗口重新打開爲止。
    堅持定時器的原理:當 TCP 服務器收到了客戶端的 0 滑動窗口報文時,啓動一個定時器來計時,並在定時器溢出的時向客戶端查詢窗口是否已經增大,如果得到非零的窗口就重新開始發送數據,如果得到零窗口就再開一個新的定時器準備下一次查詢。

  • 保活計時器
    每當服務器收到客戶的信息,就將keeplive timer復位,超時通常設置2小時,若服務器超過2小時還沒有收到來自客戶的信息,就發送探測報文段,若發送了10個探測報文段(沒75秒發送一個)還沒收到響應,則終止連接。

  • 2MSL計時器
    2MSL 定時器主要是解決以下兩種情況:
    TIME_WAIT 確保有足夠的時間讓對端收到了ACK,如果被動關閉的那方沒有收到 ACK,就會觸發被動端重發 FIN。因爲最後一次確認應答 ACK 報文段很有可能丟失,因而使被動關閉方處於在LIST_ACK 狀態的,此時被動關閉方會重發這個 FIN+ACK 報文段,在這等待的 2MSL 時間內主動關閉方重新收到這個被動關閉方重發的 FIN+ACK 報文段,因此,主動關閉方會重新發送確認應答信息,從而重新啓動 2MSL 計時器,直到通信雙方都進入 CLOSED 狀態。如果主動關閉方在 TIME_WAIT 狀態不等待一段時間就直接釋放連接並進入 CLOSED 狀態,那麼主動關閉方無法收到來自被動關閉方重發的 FIN+ACK 報文段,也就不會再發送一次確認 ACK 報文段,因此被動關閉方就無法正常進入CLOSED 狀態。
    有足夠的時間讓這個連接不會跟後面的連接混在一起。防止已失效的請求連接出現在本連接中。在連接處於 2MSL 等待時,任何遲到的報文段將被丟棄,因爲處於 2MSL等待的、由該插口(插口是IP和端口對的意思,socket)定義的連接在這段時間內將不能被再用,這樣就可以使下一個新的連接中不會出現這種舊的連接之前延遲的報文段。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章