天天看點

linux關于tcp協定ack的實作--總結和公平性問題

tcp是一個可靠連接配接的協定,但不要指望它是什麼理論的實作,它是實踐的東西,任何實踐的東西背後都不是一個理論,而是一大堆理論,tcp正是單一停等,GBN(回退N)以及SR(選擇重傳)的結合體,單一停等是最原始的理論,但是帶寬使用率太低了,後面的GBN實作了流水線式的資料發送和确認,可靠連接配接的根本就在于确認-ack,而GBN的ack完全是基于接收方的,接收方很簡單的隻發送最後一個按序到達的封包的序列号最為确認号,而發送端收到以後将重傳該确認号之後的所有封包,這樣實作很簡單,要考慮的事情也不多,但是可能會導緻大量不必要的重傳動作,是以SR就報上了名來,隻要接收端收到一個封包就給予确認,發送方将已經被确認的分組從重傳連結清單删除,然後如果被确認的分組在視窗的最左邊,那麼向前移動發送視窗,這就解決了GBN中的一系列問題,可是新的問題就是實作起來可能更複雜了,收發雙方對于ack的處理都很複雜。

     linux的tcp實作實質上是以GBN為根本,但是内置了SR算法的支援,正和RFC的建議一緻,SR在RFC2018中被描述,而它是作為一個tcp選項被加入協定的,也就是說tcp的實作的骨架還是gbn,但是如果你想使用sr的特性,那麼需要通過tcp頭的選項來支援,linux實作了這一點,并且将發送ack,接收ack,處理sr,以及重傳等動作完全分離,發送ack完全按照gbn的方式,如果需要sack的話,那麼另外填寫選項,對于接收ack并處理,也是按照GBN的方式,但是其間需要檢查是否備援ack積累到了一定量,接收ack是tcp_ack處理的,雖然它基于,但它絲毫不必擔心gbn的大量重傳問題,因為重傳動作完全是tcp_ack以外的,它将根據sack相關的資訊處理重傳,而不是根據gbn的原則重傳分組。

     正是ack保證了連接配接的可靠性,同時ack也左右了tcp的擁塞控制以及流量控制動作,進而使得tcp實作帶寬的公平性(加增乘減),但是公平性隻是針對tcp内部而言的,如果大量瘋狂的udp視訊傳輸于骨幹網,由于udp沒有擁塞控制,它會占去大量資源而不後退,而tcp由于丢包或者延遲已經感覺到了擁塞,于是tcp們紛紛減緩發送,于是就讓給udp更大的帶寬,雖然這種綏靖不是有意的,但是這個問題卻是亟待解決的,目前無法在協定本身找到完美的解決方案,而隻能通過諸如路由器的流控或者在linux上使用iptables配置相關政策來實作。

     是以tcp是一個諸多理論的混合體,而linux實作的tcp又是諸多實作建議的混合體。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271787

繼續閱讀