傳輸層協議TCP、UDP獲得本地介面的MTU還是很簡單的,只要通過簡單的函數調用即可。可是,得到本地的MTU值並不能保證本地發出的IP報文,在通往目的地的路徑上不被分片。

根據木桶理論,一個木桶能裝多少水,不是由最高的木板來決定的,而是由最低的木板來決定的。同理,在通向目的地的路徑上,決定傳輸最大單元尺寸是最小的路由器的MTU,而不是最大的MTU。

儘管獲知通信雙方之間路徑最小MTU有一定難度,但是TCP協議還是決定用自己的方法來找到它。

TCP使用MSS option 在握手連接時,雙方互相交換各自的MSS,然後雙方約定使用兩個MSS中的小者,但這種方法並不有效。

比如客戶端MTU = 1500, 伺服器端MTU = 1500,雙方的MSS = 1460,雙方就協商使用1460 byte 來傳輸TCP segment。 問題來了,客戶端通向ISP的光纖路由器是PPPoE撥號,將會在正常的IP報文頭添加8 byte的PPPoE頭,相當於變相擠佔了IP報文8 byte的空間,留給IP報文的MTU = 1500 -8 =1492,那麼客戶端與伺服器的1500 byte 的IP報文最終會被分片。

如何探測路徑中的最小的MTU?只要讓IP報文設置DF= 1即可,這樣一旦需要分片而無法分片,會發送錯誤消息通知源。源主機就會獲悉最小的MTU的數值,源主機的IP層會記錄一條特殊的主機路由,這條主機路由通向唯一的目的地,並標註其最小MTU,這樣以後和該目的地主機的通信將使用該最小MTU。 同時,源主機IP層會通過消息通知的方式,通知TCP關於路徑中最小MTU,這樣該TCP session會相應地減小自己的最大傳輸單元。

這種方法固然好,但是由於某些路由器可能禁止了ICMP錯誤通知功能,動態路徑MTU檢測,往往造成通信障礙。 Windows 10 統一使用 MTU = 1300的方法,可能是一個較好的方法,可以避免99%+以上網路場景的分片。

更多文章,歡迎閱讀:https://mp.weixin.qq.com/s/xZbsLy9bUjuAgB3JC0B8HQ


參考HTTP協議頭 Content-Size

反而是粘包的問題 比較麻煩 這裡是同步還是非同步分片兒傳輸 學問就大了~


試出來的 有通知機制


我想,你應該是想獲得一條網路路徑上所有節點中最小的mtu吧?如果是這樣,一個可行的方法是包裝指定長度的ping包發送給對端,同時設置不可拆包的標誌,如果能收到返回,說明網路路徑上最小的mtu不比這個小,然後再增大包大小,直到收不到回包為止,之前成功的最大包大小就是這個mtu值了。可以查看ping命令的幫助,看哪個選項控制這些參數。計算的時候注意也要把IP包頭的大小算在內。

樓上已回答。實例數值是協議工作中具體協商的。你要是想找到,可以抓包自己看,也可以編程獲取


推薦閱讀:
相关文章