tcp、udp、分包粘包

MTU

UDP和TCP報頭使用兩個字節存放端口號,所以端口號的有效範圍是從0到65535。動態端口的範圍是從1024到65535。每個以太網幀都有最小的大小64Bytes最大不能超過1518Bytes,對於小於或者大於這個限制的以太網幀我們都可以視之爲錯誤的數據幀,一般的以太網轉發設備會丟棄這些數據幀。 

 由於以太網EthernetII最大的數據幀是1518Bytes這樣,刨去以太網幀的幀頭(DMAC目的MAC地址48bits=6Bytes+SMAC源MAC地址48bits=6Bytes+Type域2Bytes)14Bytes和幀尾CRC校驗部分4Bytes那麼剩下承載上層協議的地方也就是Data域最大就只能有1500Bytes這個值我們就把它稱之爲MTU

UDP 包的大小就應該是 1500 - IP頭(20) - UDP頭(8) = 1472(Bytes)

TCP 包的大小就應該是 1500 - IP頭(20) - TCP頭(20) = 1460 (Bytes)

分包與否

如果我們定義的TCP和UDP包沒有超過範圍,那麼我們的包在IP層就不用分包了,這樣傳輸過程中就避免了在IP層組包發生的錯誤;如果超過範圍,既IP數據報大於1500字節,發送方IP層就需要將數據包分成若干片,而接收方IP層就需要進行數據報的重組。更嚴重的是,如果使用UDP協議,當IP層組包發生錯誤,那麼包就會被丟棄。接收方無法重組數據報,將導致丟棄整個IP數據報。UDP不保證可靠傳輸;但是TCP發生組包錯誤時,該包會被重傳,保證可靠傳輸。在IP層(網絡層)分包組包。

粘包與否

TCP常常被稱作一種“流協議”,會進行擁塞/流量控制。發送端爲了將多個發往(send,write)接收端的包,更有效的發到對方,使用了優化方法(Nagle算法),將多次間隔較小且數據量小的數據,合併成一個大的數據塊,然後進行封包,再發往接收端(recv,read),所以一定處理粘包問題,其一方案是有效負載中加入length數據。

UDP不存在粘包問題,是由於UDP發送的時候,沒有經過Negal算法優化,不會將多個小包合併一次發送出去。另外,在UDP協議的接收端,採用了鏈式結構來記錄每一個到達的UDP包,這樣接收端應用程序一次recv只能從socket接收緩衝區中讀出一個數據包。也就是說,發送端send(write)了幾次,接收端必須recv(read)幾次(無論recv時指定了多大的緩衝區)。

Internet(非局域網)上的標準MTU值爲576字節,所以建議在進行Internet的UDP編程時,最好將UDP的數據長度控制在548字節 (576-8-20)以內。

當發送的有效數據大於1472字節時,也就是說IP數據報大於1500字節,大於MTU,這個時候發送方IP層就需要分片(fragmentation)。把數據報分成若干片,使每一片都小於MTU.而接收方IP層則需要進行數據報的重。這樣就會多做許多事情,而更嚴重的是,由於UDP的特性,當某一片數據傳送中丟失時,接收方便無法重組數據報.將導致丟棄整個UDP數據報。此時所以我們自己分包(片),組包(片)。

TCP、UDP數據包最小值的確定

根據第一幅圖,發送的udp有效數據最好超過46-IP頭(20) - UDP頭(8) = 18字節,發送的tcp有效數據最好超過46-IP頭(20) - TCP頭(20) = 6字節,否則可能會出現接收不到的情況。


參考:

https://blog.csdn.net/caoshangpa/article/details/51530685      

https://blog.csdn.net/hik_zxw/article/details/48398935

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章