tcp重傳機制 對端滑動窗口一直為0時如何處理?

有一個長連,應用層write 1K位元組數據到os的socket buffer後,對端機器滑動窗口一直為0,或者發送一部分數據後,一直未收到ack,數據一致無法發送到對端,tcp會如何處理當前的這個數據,是超過重試次數後通知應用層還是一直嘗試重發?

如果一直留著發送緩存中,tcp的超時重傳會持續多久,如果應用層一直不主動干預,留在發送緩存的數據是不是會一直存在呢


在回答這個問題之前,先問一個問題,通信雙方的客戶端與伺服器是AI機器人哇?不是!那是什麼?是兩個不夠智能的僵硬機器,根據人類的指令輸入來完成通信。

通信過程繁複兀雜,但撥開雲霧會發現,其實通信過程可以分為兩大類:

1)事件觸發(event trigger) 簡稱ET
2)定時器觸發 ( timer trigger) 簡稱 TT

我們以一個例子(TCP建立連接的三次握手)來說明兩者的區別:

1.1 事件觸發
A主動發起對B的TCP連接(SYN),這是ET還是TT呢? 是ET,因為是位於A後的老王發出的指令,比如在瀏覽器里輸入B 的網址,然後觸發TCP連接

1.2 定時器觸發
但是如果SYN在發給B 的過程中丟了呢?是否還需要老王再次提交指令?如果是,那這個TCP協議棧就太不友好了,事實上商用的TCP會緩存用戶的連接指令,並啟動一個重傳定時器,定時器超時,無需老王的干預,TCP會自動重傳連接指令,這就是定時器觸發

2.1 事件觸發
假設B接收到A的連接請求,這個就是事件觸發,是由於外部事件而觸發的動作,動作是什麼呢? 發SYN + ACK。

2.2 定時器觸發
B同樣擔心自己的SYN + ACK丟失,所以也會啟動一個重傳定時器,如果在超時時間內沒有接收到A的ACK,則會觸發重傳動作,如果收到ACK,則關閉定時器。

3 事件觸發
假設A接收到B的SYN + ACK,這是一個外部事件觸發的動作,動作是
1)關閉重傳定時器
2)發送ACK
3)將TCP狀態更新為established

對於3.2里的ACK要不要啟動重傳定時器?不需要,如果是,會無限循環到永遠。

以上通過3-way 握手解釋了事件觸發以及定時器觸發的區別,對於題主的問題就非常好回答了。

對於應用層提交給TCP的數據(事件觸發),觸發的動作是
1)發送數據 並緩衝數據
2)為數據啟動重傳定時器

如果接到對方ACK,事件觸發的動作是
1)關閉定時器
2)釋放緩存

如果定時器超時也沒有接收到ACK,則定時器觸發,動作是
1)重傳數據
2)記錄重傳次數

如果重傳次數滿,比如重傳8次,則是事件觸發,動作是
1)reset 或關閉TCP連接
2)通知應用層出錯

再來回答第二個問題,B告訴A,window size =0,則A認為這是一個外部事件,觸發一個動作
1)啟動探測定時器( persistent timer)

如果在PT超時之前接收到B的window &>0, 則事件觸發,動作為
1)關閉PT
2)有數據則繼續發送數據
3)更新自己的滑動窗口右側

如果在PT超時之前沒有接收到B window更新,則定時器觸發,動作為
1)發送一個byte 合法數據(滑動窗口內)或非法數據(滑動窗口外)
2)刷新定時器
3)記錄超時次數

如果超時次數到達極限,則事件觸發,動作為
1)reset 或關閉TCP連接
2)通知應用層出錯原因

總結
整個通信過程只需要一次用戶輸入(用戶事件),接下來的通信過程全部依賴事件觸發、定時器觸發而產生的動作自動完成,或如行雲流水(順利)或磕磕絆絆(不順利),但無需用戶干預。


你可以很容易地重現這個場景,再用 tcpdump 看看就知道了。


接收端通告的窗口大小變成0,發送端會發一個1位元組的段(就是下一位元組的數據,沒新的數據段發送的時候發一個ack)(TCP零窗口探測),強制接收端重新宣告下一個期望的位元組和窗口大小。如果接收方回復窗口大小仍然為零,則發送方的探測定時器加倍。沒有收到ACK時,發送探測包的最大次數之後連接超時。


如果是linux,關閉滑動或者縮小其rmem


有知友提到了0窗口探測,這裡我做一個補充, 窗口探測是發送端滑動窗口為零時進行的,當接收方滑動窗口變零後,也就是接收到發送方滑動窗口裡的全部數據後,會將最後一個位元組序號+1作為確認號返回發送方,發送方的滑動窗口此時變零,引起死鎖(因為窗口為0,沒東西發了,接收方沒東西收也不會反饋),才需要進行0窗口探測的,;如果這個確認數據包中途丟失,會出現接收方滑動窗口為0但是發送方還是維持之前的大小,此時發送方還會通過超時重傳機制發送給接收方,接收方一樣會返回確認,並不是接收方滑動窗口為0時,發送方就會進行0窗口探測,而是發送方為0時才進行 。

----以下為原答案---

對端滑動窗口為0,你發過去的數據包也會被丟棄吧,因為沒有收到對端新的期望的確認號,發送端在發送緩存中的已發送但未確認的位元組就不會刪,只能進行超時重傳,應用層不用多次再發。具體可以參考謝希仁著的《計算機網路》運輸層那一章,tcp可靠傳輸的實現和tcp流量控制兩節內容,對這種情況有詳細論述。


tcp重傳有一個往返時間RTT 是隨機的 有一個公式
tcp通信要基於ip的可達性 像你說的 tcp發過去包 多端存緩存里 都無法處理了 可見對端網路連通性極差
至於題主如果想研究一些抬杠的東西 建議你研究一下qos 看一看緩存里的數據處理過程


推薦閱讀:

為什麼TCP4次揮手時等待為2MSL?
在計算機領域中,有哪些令你拍案叫絕的思想?
乙太網與互聯網有什麼區別?
埠號和協議號的區別在哪裡?
10MB寬頻會有這樣的速度嗎?

TAG:Linux | 計算機網路 | 計算機科學 | TCP | 網路協議 |