用UDP一定比用TCP快嗎?
假設我們需要在a電腦的進程發一段數據到b電腦的進程我們可以選擇使用TCP或UDP協議進行通信。
對于TCP這樣的可靠性協議每次消息發出后都能明確知道對方有沒有收到,就像打電話一樣,只要“喂喂"兩下對方就能回你個"hi hi"你就知道對方有沒有在聽
UDP就像是給郵政的信箱寄信一樣,你寄出去的信根本就不知道對方有沒有正常收到丟了也是有可能的
可以通過創建socket的方式來選擇使用TCP還是UDP?
fd = socket(AF_INET,SOCK_STREAM,0):是指使用字節流傳輸數據,就是TCP協議
fd = socket(AF_INET,SOCK_DGRAM ,0):是指使用數據報傳輸數據,就是UDP協議
返回的FD是指socket句柄,可以理解為socket的身份證號,這時候根據協議的不同還要執行一些操作,如果一切順利就可以開始傳輸消息,如果不順利,比如消息發到一半丟包了,那UDP和TCP的態度就不太一樣了。
- UDP:管我什么事
- TCP(可靠性):是不是發的太快了,是不是鏈路太堵了,不過放心會重發的。
TCP為了保證可靠性:
重傳機制:TCP會給發出的消息打上一個編號,也就是sequence,接收方收到后回一個確認ack包,發送方可以通過ack的數值知道接收方收到了哪些sequence的包,如果長時間等不到對方的確認TCP就會重新發送消息這就是所謂的重傳機制,重傳對性能影響比較嚴重,是下下策。
TCP就需要思考怎么盡量避免重傳,因為數據發送方和接收方處理數據能力可能不同,以此可以根據雙方的能力去調整發送的數據量就好了,就有了發送和接收窗口
接收方當前能接收的數據量大小TCP根據窗口的大小去控制自己發送的數據量,這樣就能大大減少丟包的概率比如一開始窗口大小為2。
收到一個數據包之后窗口就變成了1,此刻只能再收一個數據包。
當接收窗口變為0時,也就是所謂的0窗口,此時發送端停止發送數據接收方接收到數據之后會不斷處理,處理能力也不是一成不變的,有時候處理的快一些就可以多收點數據,處理的慢點,就希望對方能少發點數據,像這種根據自身能力不斷調整窗口的機制就是所謂的滑動窗口機制
通過滑動窗口機制TCP實現了流量控制,但這還不夠,有時候發生丟包并不是因為發送方和接收方的處理能力問題導致的而是跟網絡環境有關,將網絡想象為一條公路,馬路上可能堵滿了別人家的車只留下三輛車的空間,你也沒辦法同時上路
TCP希望能感知到外部網絡環境根據網絡環境及時調整自己的發包數量,但外部環境這么復雜,TCP是怎么感知到的呢?
TCP會先慢慢試探的發數據,不斷加碼,數據量越發越多,先發一個,再發兩個,再發四個,直到出現丟包,這樣TCP就知道當前網絡大概吃得消幾個包了,這就是所謂的擁塞控制機制
流量控制和擁塞控制的關系
- 流量控制:針對的是單個連接數據處理能力的控制
- 擁塞控制:針對的是整個網絡環境數據處理能力的控制
都是怎么降低重傳的概率,降低帶來的影響
當我們需要發送一個超大的數據包時,如果數據包丟了就得重傳同樣大的數據包
但如果將其分成一小段一小段,就算丟了也就只需要傳那一小段就好了,大大減少了重傳的壓力
這就是TCP的分段機制
所謂一小段的機制在傳輸層叫MSS(maximum segment size),數據包長度大于MSS,則會分成n個小于等于MSS的包
如果數據包還大于MTU(maximum transmit unit):還會繼續分包
一般情況下MSS等于MTU減去40 byte
所以TCP分段后到了IP層大概率就不會再分片了,既然數據包會被分段,鏈路又這么復雜還會丟包,那么數據包亂序也就顯得不奇怪了。
亂序的問題TCP也考慮到了:依靠數據包的sequence,接收方就能知道數據包的先后順序,后發的數據包先到就先放到專門的亂序隊列中等數據都到齊后 重新整理好數據包順序后再給到用戶,這就是亂序重排機制
網絡環境列路很長還復雜,數據丟包是很常見的,平常用TCP做各種數據傳輸完全對這些事情無感知
TCP三大特性:
UDP沒有這么多復雜的特性所以很快
這就是大部分人認為UDP比TCP快的原因,實際大部分情況下確實是這樣
有沒有用了UDP但卻比TCP慢的情況
UDP的用途,大部分人不會嘗試直接拿裸UDP放到生產環境中去做項目
UDP的價值:本質是內核提供的一個最小網絡傳輸功能,很多時候,都號稱自己用了UDP,但實際上都很忌憚他的丟包問題,所以大部分情況下都會在UDP的基礎上做各種不同程度的應用層可靠性保證,某些游戲為了追求低延遲,不同程度使用了UDP,比如王者農藥(KCP)
適合用于音視頻傳輸,因為這些場景允許丟包
雖然選擇了使用UDP,但是還是會在這一基礎上做一些重傳機制
如果現在需要傳一個特別大的數據包,在TCP內部會根據MSS的大小分段這時候進入到IP層之后每個包大小都不會超過MTU,因此IP層一般不會再進行分片,這時候發生丟包只需要重傳每個MSS分段就夠了。
但對于UDP本身并不會分段,如果數據過大到了IP層就會進行分片,此時發生丟包再次重傳就會重傳一整個大數據包,對于上面這種情況使用UDP就比TCP慢
解決起來也不復雜:如果使用UDP的應用層也實現了分段機制就不會出現上述的問題。