TCP協議存在那些缺陷?
100人眼裡有100種哈姆雷特,談談我眼中的TCP。
TCP做為一種可靠傳輸協議,其核心目標是把應用層的數據正確、可靠、高效傳輸到對端,而TCP所依賴的IP網路是一個原始的叢林世界,丟包、亂序、延遲不固定。
TCP有一個孿生兄弟叫UDP,UDP是一大老粗,但非常聽話。UDP在IP網路叢林里,嚴格執行自己的主人(應用層)的旨意,主人讓發1000個/秒UDP包,UDP就一定會發那麼多,也許這1000個包最終到達目的地的只有200個,其它的800個消失在叢林世界裡無影無蹤。
TCP是舉止優雅的紳士,對叢林世界的潛規則很反感,但又有極強的適應能力,能夠從容應對一切的挑戰。TCP也接到老闆的吩咐:把1000個數據包1秒之內發到目的地!
TCP委婉地表達自己的想法,可以準確無誤地發到目的地,但時間無法保證!
TCP凡事喜歡預約,每當需要拜訪對方時,總會提前打過招呼(建立連接),只有對方在、並且接受預約(連接建立),才會帶著老闆的數據包去拜訪對方。
TCP是這麼做的:
先發一個包,等一個包的確認收到,可以得到一個往返時間RTT
發兩個,收到確認,得到第二個RTT,與第一個相加算平均SRTT
…
一直兩倍的指數增長,一直計算SRTT。
直到檢測到丟包,或retransmission timer 超時、或收到至少三次duplicated ACK,
1.TCP決定在SRTT時間內發送個數指數減半
2.如果收到ACK,則持續計算SRTT,發送個數線性增長,一個SRTT多發一個包。
3.如果依然沒有收到ACK,重複步驟1、2
這是TCP的自適應流量控制演算法,決定TCP能發多快,由這個公式得到:
Delivery Rate = CWND/SRTT,其中
CWND = 可發送包的個數 * 包的大小
SRTT 是平滑RTT,動態測量的結果
如果SRTT不變,CWND越大,發送速率越快。
如果CWND不變,SRTT越小,發送速率越快。
但一旦網路擁堵,路由器緩存隊列使得SRTT變大,所以rate 會變小。
如果緩衝隊列尾丟(溢出),意味著有丟包,發送方肯定能檢測出,指數減小CWND,這樣rate 也會突減1/2。
TCP就是通過這種小速率探測網路擁堵、指數增加發送速度、檢測到丟包、發送速率減半、直到不再檢測到丟包、線性增長發送速率、檢測到丟包、再指數減小發送速率…
TCP流控演算法的關鍵,是基於丟包,有否丟包是唯一的判斷依據,是加油門還是踩剎車。
但TCP由於對網路了解的很片面,無法分辨丟包是什麼原因造成的
1)網路真的擁堵而丟包
2)線路質量差CRC校驗失敗丟、或信號干擾丟
3)IP包亂序而引起的誤判
只有情況1是需要踩剎車的,而情況2、3並不需要。
Google BBR演算法則提出基於帶寬實時測量的演算法,對於每個有數據的TCP包都測量其RTT,動態計算SRTT,這個比傳統TCP計算的SRTT更精準,因為傳統的TCP是一個SRTT時間周期內測量一次,而不是每個有數據的TCP包都測量。
根據實時帶寬值的趨勢,是增還是減,如果增,說明帶寬還有空間,可以樂觀,在當前的delivery rate 的基礎上 * 大於1的係數,等於加小油門,發送速率攀升。
如果是減,則需要謹慎,在當前的delivery rate 的基礎上 * 小於1的係數,等於小踩剎車,發送速率放緩。
BBR演算法不依賴於丟包,可以克服傳統TCP對丟包的過分敏感與過激反應,避免發送速率驟增與驟減,使得整體發送速率在一個小範圍內波動,更平緩、更平滑。
這是傳統TCP流控演算法的一個改進。
至於TCP其他的需要改進的,已經通過TCP option做了補丁,比如
Scaling window 應對長肥管道
Selective ACK 應對高丟包率場景
Timestamp 應對序列號回滾、RTT測量的精度
Authentication Option 應對數據完整性挑戰
TCP Cookie 應對SYN Flooding DOS攻擊
FAST TCP Open 應對TCP傳輸數據延時大
總體而言,TCP在傳統的網路上工作的非常好,只是因為一些新的網路狀況導致TCP不能很好的適應,這些就是需要改進的方向。
首先是流控演算法不能很好的適應高帶寬高延遲的場景,因為ack確認因為傳輸延遲不能及時送達導致傳輸速度遠低於理論的傳輸帶寬。
還有擁塞控制演算法也不能很好的適應網路不太穩定的場景(比如無線網路),TCP的擁塞控制認為丟包是因為網路傳輸飽和,所以一但出現丟包就採取指數級避讓,而無線網路因為短暫的信號干擾導致的丟包並不是因為網路傳輸飽和,此時採取指數級避讓是不合適的,會導致無線傳輸的速度驟降。
關於這個已經有很多改進的演算法了,比如BBR。@喬捷 回答了端上的,我說一下雲上的問題吧。
和端上高帶寬高延遲相反,雲上的問題在於超高的帶寬(10-100 Gbps)和超低的延遲(10-100 us)需求,傳統 TCP 以丟包來檢測可用帶寬的思路會導致重傳(1-10ms),這對許多面向用戶的應用是災難性的。傳統 TCP 過於保守的啟動階段浪費了帶寬,過於激進的增長又使得交換機緩衝隊列無限制增長直至出現擁塞,再加上雲中極易出現的多對一的場景,導致傳統 TCP 不能適應許多數據中心級別應用的需求。
詳細的闡述可以去看 DCTCP 這個協議,具體部署到數據中心的協議棧雖然是高度定製化的,但一般也是在 DCTCP 之上做出的一些改進,想解決的問題基本是一致的。
安全性缺陷:
TCP使用三次握手機制來建立一條連接,握手的第一個報文為SYN包;第二個報文為SYN/ACK包,表明它應答第一個SYN包同時繼續握手的過程;第三個報文僅僅是一個應答,表示為ACK包。若A放為連接方,B為響應方,其間可能的威脅有:
1. 攻擊者監聽B方發出的SYN/ACK報文。
2. 攻擊者向方發送RST包,接著發送SYN包,假冒A方發起新的連接。
3. B方響應新連接,並發送連接響應報文SYN/ACK。
4. 攻擊者再假冒A方對B方發送ACK包。
這樣攻擊者便達到了破壞連接的作用,若攻擊者再趁機插入有害數據包,則後果更嚴重。TCP協議把通過連接而傳輸的數據看成是位元組流,用一個32位整數對傳送的位元組編號。 初始序列號(ISN)在TCP握手時產生,產生機制與協議實現有關。攻擊者只要向目標主機發送一個連接請求,即可獲得上次連接的ISN,再通過多次測量來回傳輸路徑,得到進攻主機到目標主機之間數據包傳送的來回時間RTT。已知上次連接的ISN和RTT,很容易就能預測下一次連接的ISN。若攻擊者假冒信任主機向目標主機發出TCP連接,並預測到目標主機的TCP序列號,攻擊者就能偽造有害數據包,使之被目標主機接受。
IP協議在互連網路之間提供無連接的數據包傳輸。IP協議根據IP頭中的目的地址項來發送IP數據包。也就是說,IP路由IP包時,對IP頭中提供的源地址不作任何檢查,並且認為IP頭中的源地址即為發送該包的機器的IP
地址。這樣,許多依靠IP源地址做確認的服務將產生問題並且會被非法入侵。其中最重要的就是利用IP欺騙引起的各種攻擊。
以防火牆為例,一些網路的防火牆只允許網路信任的IP數據包通過。但是由於IP地址不檢測IP數據包中的IP源地址是否為放送該包的源主機的真實地址,攻擊者可以採用IP源地址欺騙的方法來繞過這種防火牆。另外有一些以IP地址作為安全許可權分配依據的網路應用,攻擊者很容易使用IP源地址欺騙的方法獲得特權,從而給被攻擊者造成嚴重的損失。事實上,每一個攻擊者都可以利用IP不檢驗IP頭源地址的特點,自己填入偽造的IP地址來進行攻擊,使自己不被發現。
就我個人來看,感覺tcp最難受的就是原來假設的丟包是擁塞引起的,只是因為擁塞引起的。
這個現象導致在現在高速鏈路下,反應太慢。
所以覺得tcp支持多連接是必需的改進。另外,希望能夠增加一些其他的信息指示來提高控制能力。例如,建立tcp時,通報一下雙方所在的網路情況(帶寬、介質、跳數)等等
TCP存在的主要缺陷有:
1)性能比UDP低,包括延遲時間等。
2)TCP的crc校驗位只有16位, 當出現錯誤時,有1/65535的概率不能夠被檢測出來,不夠可靠。
3)TCP存在粘包的情況,就是就是我們收到的數據流,並且有可能是多個數據包合併的內容,而不是數據塊,在後續處理的過程中一定要單獨處理。
4)目前TCP層的設計過於陳舊,畢竟是60-70年代的東西, 很多地方不夠理想。例如:單個連接只能承載一套數據流,這樣導致象新浪這樣的網站,打開網頁要發很多TCP連接。如果在底層設計承載多套數據流就要好很多。
5)TCP的內部參數默認很多不完全適應現在高速網路的需求,當時的網路和現在不一樣,例如:現在我們為了加快ip包的傳遞往往設置了nodelay,關閉一些過於老化的模塊。
TCP是高可靠性的協議,為了提高可靠性,必然要犧牲一些其它方面的性能作為代價,這是必然的。這些犧牲的性能就是其所謂的缺陷了。
1,確保高可靠性就需要知道通信對方的狀態,那就必須要建立連接、維護連接、釋放連接,這當然就要有對應的開銷。以「握手」的方式建立和釋放連接(有關TCP的三次握手就不贅言了,其它回答已經說了很多了),導致延時和數據收發雙方的資源分配的開銷。而對應的UDP協議由於是無連接的,自然無需延時和資源開銷。因此,延時和資源開銷算是第一種「缺陷」了。
先寫到這,航班要起飛了,到目的地後再繼續。
推薦閱讀:
※舍友經常用我的電腦上黃網,又不想明說,如何通過設置電腦解決呢?
※為什麼計算機領域的概念如此難以理解?
※如何處理網上個人信息泄露?
※初三畢業的學生,如何把有限的時間、極限的努力正確投入 IT 行業?
※大家對於 CSDN 等網站的用戶密碼泄漏事件怎麼看?