日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

原文出自:公眾號 golang小白成長記

原文鏈接:
https://mp.weixin.qq.com/s/VLHCu6b5Anx8HEj_gQZfOg

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

什么是TCP分段和IP分片

我們知道網絡就像一根管子,而管子吧,就會有粗細。

一個數據包想從管子的一端到另一端,得過這個管子。(廢話)

但數據包的量有大有小,想過管子,數據包不能大于這根管子的粗細。

問題來了,數據包過大時怎么辦?

答案比較簡單。會把數據包切分小塊。這樣數據就可以由大變小,順利傳輸。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

回去看下網絡分層協議,數據先過傳輸層,再到網絡層。

這個行為在傳輸層和網絡層都有可能發生。

在傳輸層(TCP協議)里,叫分段

在網絡層(IP層),叫分片。(注意以下提到的IP沒有特殊說明的情況下,都是指IPV4

那么不管是分片還是分段,肯定需要按照一定的長度切分。

在TCP里,這個長度是MSS。

在IP層里,這個長度是MTU。

MSS和MTU是什么關系呢?這個在之前的文章里簡單提到過。這里單獨拿出來。

MSS是什么

MSS:Maximum Segment Size 。TCP 提交給 IP 層最大分段大小,不包含 TCP Header 和 TCP Option,只包含 TCP Payload ,MSS 是 TCP 用來限制應用層最大的發送字節數。
假設 MTU= 1500 byte,那么 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte,如果應用層有 2000 byte 發送,那么需要兩個切片才可以完成發送,第一個 TCP 切片 = 1460,第二個 TCP 切片 = 540。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

如何查看MSS?

我們都知道TCP三次握手,而MSS會在三次握手的過程中傳遞給對方,用于通知對端本地最大可以接收的TCP報文數據大?。ú话琓CP和IP報文首部)。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

比如上圖中,B將自己的MSS發送給A,建議A在發數據給B的時候,采用MSS=1420進行分段。而B在發數據給A的時候,同樣會帶上MSS=1372。兩者在對比后,會采用小的那個值(1372)作為通信的MSS值,這個過程叫MSS協商。

另外,一般情況下MSS + 20(TCP頭)+ 20(IP頭)= MTU,上面抓包的圖里對應的MTU分別是1372+40 和 1420+40。同一個路徑上,MTU不一定是對稱的,也就是說A到B和B到A,兩條路徑上的MTU可以是不同的,對應的MSS也一樣。

三次握手中協商了MSS就不會改變了嗎?

當然不是,每次執行TCP發送消息的函數時,會重新計算一次MSS,再進行分段操作。

對端不傳MSS會怎么樣?

我們再看TCP的報頭。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

其實MSS是作為可選項引入的,只不過一般情況下MSS都會傳,但是萬一遇到了哪臺機器的實現上比較調皮,不傳MSS這個可選項。那對端該怎么辦?

如果沒有接收到對端TCP的MSS,本端TCP默認采用MSS=536Byte。

那為什么會是536?

536(data) + 20(tcp頭)+20(ip頭)= 576Byte

前面提到了IP會切片,那會切片,也就會重組,而這個576正好是 IP 最小重組緩沖區的大小。

MTU是什么

MTU: Maximum Transmit Unit,最大傳輸單元。其實這個是由數據鏈路層提供,為了告訴上層IP層,自己的傳輸能力是多大。IP層就會根據它進行數據包切分。一般 MTU=1500 Byte。
假設IP層有 <= 1500 byte 需要發送,只需要一個 IP 包就可以完成發送任務;假設 IP 層有 > 1500 byte 數據需要發送,需要分片才能完成發送,分片后的 IP Header ID 相同,同時為了分片后能在接收端把切片組裝起來,還需要在分片后的IP包里加上各種信息。比如這個分片在原來的IP包里的偏移offset。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

如何查看MTU

在mac控制臺輸入 ifconfig命令,可以看到MTU的值為多大。

$ ipconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    ...
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ...
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
    ...

可以看到這上面有好幾個MTU,可以簡單理解為每個網卡的處理能力不同,所以對應的MTU也不同。當然這個值是可以修改的,但不在今天的討論范疇內,不再展開。

在一臺機器的應用層到這臺機器的網卡,這條鏈路上,基本上可以保證,MSS < MTU。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

為什么MTU一般是1500

這其實是由傳輸效率決定的。首先,雖然我們平時用的網絡感覺挺穩定的,但其實這是因為TCP在背地里做了各種重傳等保證了傳輸的可靠,其實背地里線路是動不動就丟包的,而越大的包,發生丟包的概率就越大。

那是不是包越小就越好?也不是

但是如果選擇一個比較小的長度,假設選擇MTU為300Byte,TCP payload = 300 - IP Header - TCP Header = 300 - 20 - 20 = 260 byte。那有效傳輸效率= 260 / 300 = 86%

而如果以太網長度為1500,那有效傳輸效率= 1460 / 1500 = 96% ,顯然比 86%高多了。

所以,包越小越不容易丟包,包越大,傳輸效率又越高,因此權衡之下,選了1500。

為什么IP層會分片,TCP還要分段

由于本身IP層就會做分片這件事情。就算TCP不分段,到了IP層,數據包也會被分片,數據也能正常傳輸

既然網絡層就會分片了,那么TCP為什么還要分段?是不是有些多此一舉?

假設有一份數據,較大,且在TCP層不分段,如果這份數據在發送的過程中出現丟包現象,TCP會發生重傳,那么重傳的就是這一大份數據(雖然IP層會把數據切分為MTU長度的N多個小包,但是TCP重傳的單位卻是那一大份數據)。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

如果TCP把這份數據,分段為N個小于等于MSS長度的數據包,到了IP層后加上IP頭和TCP頭,還是小于MTU,那么IP層也不會再進行分包。此時在傳輸路上發生了丟包,那么TCP重傳的時候也只是重傳那一小部分的MSS段。效率會比TCP不分段時更高。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

類似的,傳輸層除了TCP外,還有UDP協議,但UDP本身不會分段,所以當數據量較大時,只能交給IP層去分片,然后傳到底層進行發送。

也就是說,正常情況下,在一臺機器的傳輸層到網絡層這條鏈路上,如果傳輸層對數據做了分段,那么IP層就不會再分片。如果傳輸層沒分段,那么IP層就可能會進行分片。

說白了,數據在TCP分段,就是為了在IP層不需要分片,同時發生重傳的時候只重傳分段后的小份數據。

TCP分段了,IP層就一定不會分片了嗎

上面提到了,在發送端,TCP分段后,IP層就不會再分片了。

但是整個傳輸鏈路中,可能還會有其他網絡層設備,而這些設備的MTU可能小于發送端的MTU。此時雖然數據包在發送端已經分段過了,但是在IP層就還會再分片一次。

如果鏈路上還有設備有更小的MTU,那么還會再分片,最后所有的分片都會在接收端處進行組裝。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

因此,就算TCP分段過后,在鏈路上的其他節點的IP層也是有可能再分片的,而且哪怕數據被第一次IP分片過了,也是有可能被其他機器的IP層進行二次、三次、四次….分片的。

IP層怎么做到不分片

上面提到的IP層在傳輸過程中因為各個節點間MTU可能不同,導致數據是可能被多次分片的。而且每次分片都要加上各種信息便于在接收端進行分片重組。那么IP層是否可以做到不分片?

如果有辦法知道整個鏈路上,最小的MTU是多少,并且以最小MTU長度發送數據,那么不管數據傳到哪個節點,都不會發生分片。

整個鏈路上,最小的MTU,就叫PMTU(path MTU)。

有一個獲得這個PMTU的方法,叫 Path MTU Discovery。

$cat /proc/sys/net/ipv4/ip_no_pmtu_disc
0

默認為0,意思是開啟PMTU發現的功能。現在一般機器上都是開啟的狀態。

原理比較簡單,首先我們先回去看下IP的數據報頭。

動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

這里有個標紅的標志位DF(Don't Fragment),當它置為1,意味著這個IP報文不分片。

當鏈路上某個路由器,收到了這個報文,當IP報文長度大于路由器的MTU時,路由器會看下這個IP報文的DF

  • 如果為0(允許分片),就會分片并把分片后的數據傳到下一個路由器
  • 如果為1,就會把數據丟棄,同時返回一個ICMP包給發送端,并告訴它"達咩!"數據不可達,需要分片,同時帶上當前機器的MTU

理解了上面的原理后,我們再看下PMTU發現是怎么實現的。

  • 應用通過TCP正常發送消息,傳輸層TCP分段后,到網絡層加上IP頭,DF置為1,消息再到更底層執行發送
  • 此時鏈路上有臺路由器由于各種原因MTU變小了
  • IP消息到這臺路由器了,路由器發現消息長度大于自己的MTU,且消息自帶DF不讓分片。就把消息丟棄。同時返回一個ICMP錯誤給發送端,同時帶上自己的MTU。
動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

  • 發送端收到這個ICMP消息,會更新自己的MTU,同時記錄到一個PMTU表中。
  • 因為TCP的可靠性,會嘗試重傳這個消息,同時以這個新MTU值計算出MSS進行分段,此時新的IP包就可以順利被剛才的路由器轉發。
  • 如果路徑上還有更小的MTU的路由器,那上面發生的事情還會再發生一次。
動圖圖解!既然IP層會分片,為什么TCP層也還要分段?

 

總結

  • 數據在TCP分段,在IP層就不需要分片,同時發生重傳的時候只重傳分段后的小份數據
  • TCP分段時使用MSS,IP分片時使用MTU
  • MSS是通過MTU計算得到,在三次握手和發送消息時都有可能產生變化。
  • IP分片是不得已的行為,盡量不在IP層分片,尤其是鏈路上中間設備的IP分片。因此,在IPv6中已經禁止中間節點設備對IP報文進行分片,分片只能在鏈路的最開頭和最末尾兩端進行。
  • 建立連接后,路徑上節點的MTU值改變時,可以通過PMTU發現更新發送端MTU的值。這種情況下,PMTU發現通過浪費N次發送機會來換取的PMTU,TCP因為有重傳可以保證可靠性,在UDP就相當于消息直接丟了。

分享到:
標簽:TCP
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定