SOCKET通訊中TCP、UDP資料包大小的確定

大囚長發表於2019-01-04

TCP、UDP資料包大小的確定

UDP和TCP協議利用埠號實現多項應用同時傳送和接收資料。資料通過源埠傳送出去,通過目標埠接收。有的網路應用只能使用預留或註冊的靜態埠;而另外一些網路應用則可以使用未被註冊的動態埠。因為UDP和TCP報頭使用兩個位元組存放埠號,所以埠號的有效範圍是從0到65535。動態埠的範圍是從1024到65535。

MTU最大傳輸單元,這個最大傳輸單元實際上和鏈路層協議有著密切的關係,EthernetII幀的結構DMAC+SMAC+Type+Data+CRC由於乙太網傳輸電氣方面的限制,每個乙太網幀都有最小的大小64bytes最大不能超過1518bytes,對於小於或者大於這個限制的乙太網幀我們都可以視之為錯誤的資料幀,一般的乙太網轉發裝置會丟棄這些資料幀。

由於乙太網EthernetII最大的資料幀是1518Bytes這樣,刨去乙太網幀的幀頭(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=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)

注*PPPoE所謂PPPoE就是在乙太網上面跑“PPP”。隨著寬頻接入(這種寬頻接入一般為Cable Modem或者xDSL或者乙太網的接入),因為乙太網缺乏認證計費機制而傳統運營商是通過PPP協議來對撥號等接入服務進行認證計費的,所以引入PPPoE。PPPoE導致MTU變小了乙太網的MTU是1500,再減去PPP的包頭包尾的開銷(8Bytes),就變成1492。不過目前大多數的路由裝置的MTU都為1500。

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

UDP資料包的長度是指包括報頭和資料部分在內的總位元組數,其中報頭長度固定,資料部分可變。資料包的最大長度根據操作環境的不同而各異。從理論上說,包含報頭在內的資料包的最大長度為65535位元組(64K)。

我們在用Socket程式設計時, UDP協議要求包小於64K,TCP沒有限定。

不過鑑於Internet上的標準MTU值為576位元組,所以建議在進行Internet的UDP程式設計時,最好將UDP的資料長度控制在548位元組 (576-8-20)以內。

就具體函式而言:

用UDP協議傳送時,用sendto函式最大能傳送資料的長度為:65535- IP頭(20) - UDP頭(8)=65507位元組。用sendto函式傳送資料時,如果傳送資料長度大於該值,則函式會返回錯誤。

用TCP協議傳送時,由於TCP是資料流協議,因此不存在包大小的限制(暫不考慮緩衝區的大小),這是指在用send函式時,資料長度引數不受限制。而實際上,所指定的這段資料並不一定會一次性傳送出去,如果這段資料比較長,會被分段傳送,如果比較短,可能會等待和下一次資料一起傳送。

相關文章