TCP MTU 問題

做網絡編程的時候大家可能會注意UDP分包的問題,當單個數據包大於MTU的時候,就會出現分包的情況,當UDP包不是純數據(UDP包一般都會有自定義的包頭)的時候,這種分包是破壞性的,所以一般UDP我們都不會讓他超過1000字節,甚至更小

但是大家往往會忽略TCP其實也受MTU的限制,在某些情況下當用TCP發送數據包(不是數據流)的時候,忽略了這個問題,也是會出現意象不到的問題

1.從以太網幀說起

以太網 Ethernet 最大的數據幀是 1518字節 。 以太網幀的幀頭 14字節和幀尾CRC校驗4字節 (共佔 18字節 ),剩下承載上層協議的地方也就是Data域最大就只剩1500字節. 這個值我們就把它稱之爲MTU。

cat /sys/class/net/eth0/mtu
1500

2.去掉IP包頭和TCP包頭

單個TCP包 實際傳輸的最大值:
1500- 20(IP頭 )-32(20字節 TCP頭和12字節TCP選項時間戳 ) = 1448 字節

3.大於這個值會發生什麼

大於1448的數據包會被拆成多份發送,接收端收到的就不會是一完整的包,數據解析出來就會出錯,
有的人把這個理解爲TCP粘包,但這明顯是分包了嘛,TCP粘包應該是另一個概念

4. 爲什麼我在本機測試沒問題

IP層 非常關心MTU,因爲 IP層 會根據MTU來決定是否把上層傳下來的數據進行分片。就像一條運輸線路的承載能力是有限的,碰到大東西要運輸,只能把大東西拆開成爲散件,分開運輸,到達目的地之後還必須能再次 組裝起來。
但你在本機上測試,會發生什麼

 cat /sys/class/net/lo/mtu
 65536

知道爲什麼你自己測可以,放到服務器上就不行了吧

5.怎麼辦

有一些人會給出你建議:
改寫read,write,
改成所謂 readall,writeall,但是你怎麼知道接收的數據一定會有多長
可靠一點的做法,每個TCP包都不要超過1448字節?
喔,可能會粘包了,麻煩呀。。。。

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