TCP的錯誤恢復我是我們定位、診斷、並最終修復網絡高延遲的最好工具。
1.TCP重傳
重傳數據包是TCP最基本的錯誤恢復特性之一,它被設計用來對付數據包丟失。
數據包丟失可能有很多原因,包括出故障的應用程序、流量負載沉重的路由器,或者臨時性的服務中斷。數據包層次上的移動速度非常快,而且數據包丟失通常是暫時的,因此TCP能否檢測到數據包丟失並從中恢復顯得至關重要。
決定是否有必要重傳數據包的主要機制叫做重傳計時器。這個計時器負責維護一個叫重傳超時(Retransmission timeout RTO)的值。每當使用TCP傳輸一個數據包時,就啓動重傳計時器。當收到這個數據包的ACK時,計時器停止。從發送數據包到接收ACK確認之間的時間被稱爲往返時間(Round-trip time RTT),將若干個這樣的時間平均下來,可算出最終的RTO值。
在最終算出RTO之前,傳輸操作系統將一直依賴於默認配置的RTT值。此項設定於主機間的初始通信,並基於接收到的數據包RTT進行調整,以形成真正的RTO。
一旦RTO確定下來,重傳定時器就被用於每個傳輸的數據包,以確定數據包是否丟失。
當數據包被髮送出去,但接收方沒有發送TCP ACK數據包時,傳輸主機就假設原來的數據包丟失了,並重傳它。重傳之後,RTO值翻倍;如果在到達極限值之前一直沒有接收到ACK數據包,那將發生另一次重傳。如果下一次重傳還是沒有收到ACK,RTO值將翻倍。每次重傳,RTO值都將翻倍,這個過程會持續到收到一個ACK數據包,或者發送方達到配置的最大重傳次數爲止。(最大重傳次數取決於傳輸操作系統上的配置,默認情況下,Windows主機最多重傳5次,在部分Linux主機則默認最多重傳15次,在操作系統中都是可以配置的。)如果發生重傳,在wireshark中可以看到retransmission包。
2.TCP重複確認和快速重傳
當接收方收到亂序數據包時,就發送重複的TCP ACK數據包。TCP在其頭部使用序號和確認號字段,以確保數據被可靠接收並以發送順序重組。
接收數據的序號+接收數據的字節數=發出的確認號
返回到發送方的確認號實際上就是接收方期待下次接收的數據包序號。
序號使數據接收方檢測數據包丟失成爲可能。當接收方追蹤正在接收的序號時,如果遇到不合順序的序號,它就知道數據包丟失了。
當接收方收到一個預料之外的序號時,它假設有一個數據包在傳輸中丟失了。爲了正確地重組數據,接收方必須要得到丟失的數據包,因此它重新發送一個包含丟失數據包序號的ACK數據包,以使發送方重傳該數據包。
當發送方收到3個來自接收方的重複ACK時,它假設這個數據包確實在傳輸中丟失了,並立刻發送一個快速重傳。一旦觸發快速重傳,其他所有正在傳輸的數據包都要靠邊,直到把快速重傳數據包發送出去爲止。(在wireshark數據包中可以看到This is a TCP duplicate ack,而發送方快速重傳時,數據包中可以看到This frame is a fast retransmission)
3.TCP流量控制
重傳和重複ACK都是TCP反應性的功能,被設計用來從數據包丟失中恢復。如果TCP沒有包含某些形式的用於預防數據包丟失的前瞻性功能,它將是一個糟糕的協議,幸好它做到了。
TCP實現了滑動窗口機制,用於檢測何時發生了數據包丟失,並調整數據傳輸速率加以避免。滑動窗口機制用用數據接收方的接收窗口來控制數據流。接收窗口是數據接收方指定的值,存儲在TCP頭部中(以字節爲單位),它告訴發送設備自己希望在TCP緩衝空間中存儲多少數據。發送方一次只能發送window size域指定的數據量。爲了傳輸更多的數據,接收方必須發送確認,以告知之前的數據已經接收到了。
當一臺繁忙的服務器處理來自多個客戶端的數據包時,服務器可能會緩慢地清空緩衝區,騰不出空間來接收新數據。如果沒有流量控制,這將導致數據包丟失和數據損壞。幸好,當服務器太繁忙,以致不能以接收窗口宣告的速率處理數據時,它可以調整接收窗口的大小。它通過減小向發送方返回ACK數據包的TCP頭部窗口大小值,達到這個目的。
4.用零窗口通知停止數據流
服務器可以發送一個數據包,指明窗口大小是0。當客戶端收到這個數據包時,它會停止所有數據傳輸,但仍通過傳輸“保活數據包”保持與服務器的連接。客戶端週期性地發送保活數據包,以檢查服務器接收窗口的狀態。一旦服務器能再次處理數據,它會響應一個非0窗口以恢復通信。
5.從TCP錯誤控制和流量控制中學到的
1)重傳數據包:發生重傳是因爲客戶端檢測到服務器沒有接收到它發送的數據。因此,你能否看到重傳取決於你在分析的通信的哪一端。如果你從服務捕獲數據,並且它確實沒有接收到客戶端發送、重傳的數據包,那你將矇在鼓裏,因爲你看不到重傳的數據包。如果你懷疑服務器端受到了數據包丟失的影響,你應該考慮在客戶端那邊捕獲流量以觀察是否有重傳數據包。
2)重複ACK數據包:當接收到亂序數據包時才觸發重複ACK。例如,如果服務器只接收到了第一個和第三個數據包,就會發送一個重複ACK以引發第二個數據包的快速重傳。
3)滑動窗口與服務器接收、處理數據的故障直接相關。服務器的某些問題可以直接導致窗口大小減少或達到0窗口狀態。
6.SACK
1)SACK是TCP選項,它使得接收方能告訴發送方哪些報文段丟失,哪些報文段重傳了,哪些報文段已經提前收到等信息。根據這些信息TCP就可以只重傳哪些真正丟失的報文段。需要注意的是隻有收到失序的分組時纔會可能會發送SACK,TCP的ACK還是建立在累積確認的基礎上的。也就是說如果收到的報文段與期望收到的報文段的序號相同就會發送累積的ACK,SACK只是針對失序到達的報文段的。SACK包括了兩個TCP選項,一個選項用於標識是否支持SACK,是在TCP連接建立時時發送;另一種選項則包含了具體的SACK信息。
2)當我們接收到ack的時候,我們會判斷sack段,如果包含sack段的話,我們就要進行處理。