傳輸層協議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
傳輸層協議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