TCP/IP 協議棧中,為什麼選擇 IP 層負責分片?
IP層來分片效率更高!
更詳細內容,請參考另外一篇文章:
車小胖談網路:澄清一些IP層的概念 - 車小胖的文章 - 知乎專欄
源主機的IP包通過一跳一跳的方式接近其目的地,在每一跳都是查看IP頭裡的目的IP地址,再和路由表進行最長匹配,然後再決定通過哪個介面進行Forwarding,如果需要分片,用IP層來分片只需要讀取IP頭信息,至於裡面傳輸的是TCP、UDP、ICMP、OSPF、GRE、ESP也不關心,也不需要關心,在IP眼中它們只是IP Payload,於是通過或硬體、或軟體硬體結合、或純粹軟體方式來分片。
如果用上層來分片,則要關心是UDP、還是TCP、還是其它,然後提交給特定的處理模塊來完成分片,一方面增加路由器的複雜度,另一方面效率也很低,路由器在處理IP層以上的高層協議,一般都是採用純粹軟體來完成的吧,那效率會更低!
回答完這個問題,我還要狠狠地強調一點:網路通信,盡一切可能避免IP的分片!為什麼?因為負責IP分片的那台主機、路由器會花費很多CPU資源來處理分片,同時負責重組IP分片的主機、路由器則需要更多的CPU資源來重組這些IP包的分片。比如一台路由器的數據處理能力是10G,如果處理分片則降低到2G左右,這還是比較高端的平台,採用硬體,軟體CPU一起協作才達到的水平,如果比較低端的平台,純粹採用CPU軟體來處理,那數據包處理能力簡直慘不忍睹!
TCP/IP協議的創造者們也知道這一點,那就是避免IP分片,於是採用了各種措施來避免:
1)Maximum Segmeant Size
一般網路介面都有一個最大傳輸單元即MTU,比如MTU=1500,什麼意思呢?如果IP包的尺寸&<= 1500,原封不動從這個網路介面發送,否則就需要分片。那聰明的你一定會說,既然知道MTU=1500,那為什麼要發超過1500的包呢?給自己找不自在?既然IP包最大1500了,那如果TCP=1480不就可以了嗎?
IP = IP Header + TCP = 20 + 1480 = 1500
TCP = TCP Header + TCP Payload = 20 + 1460 = 1480
這個TCP Payload = 1460 對應的就是TCP最大傳輸單元,我們稱之為「 Maximum Segment Size" 即MSS,那麼MSS= MTU - IP Header - TCP Header = 1500 - 20 -20 = 1460。
TCP 在三次握手的第一個SYN消息中有一個選項option 4,就是為了協商通信雙方的MSS,如果一方MSS=1460,而另一方的MSS= 8960,會選擇較小的一方即1460作為這個TCP連接的MSS,這樣雙向通信都可以避免因為IP包太大引起的分片。但是MSS能完全避免IP分片嗎?不能!還有什麼好的辦法?
2)Path MTU Discovery 即 傳輸路徑MTU的發現
還是拿第一個例子來講,IP包= 1500 從源主機發送出來了,然後在互聯網上一跳一跳奔向目的地,突然到了一台路由器上,需要從一個介面發送出去,這個介面MTU只有1000,由於IP包 1500 &> 1000,這個IP包必須分片才能出去,於是就分成了兩個IP分片發送出了,那能否讓這台路由器不分片呢?可以的,大家記得IP頭有一個標誌位DF,Don"t Fragment,如果為1,意思是這個IP包在傳輸的過程中不能分片,如果此IP包大於物理介面的MTU,請直接丟棄,並發消息告訴源主機!什麼消息?ICMP的消息,告訴包因為太大了,因為不能分片所以被丟了,並告訴源主機可以重新發小於等於MTU的包;那發什麼樣的ICMP消息?
ICMP協議里有type欄位,還有code欄位,發送type=3,code=4,MTU=1000的消息就可以了,當這個ICMP消息到達IP包的源主機,源主機知道原來是IP太大了,那最大可以發送多大的呢?ICMP消息里有,那就是MTU = 1000,於是源主機發送小於等於1000位元組的就可以避免在傳輸路徑上的分片。
那有人會說,如果IP包=1000在傳輸過程中遇到更小的MTU=500怎麼辦?呵呵,重複以上的步驟就可以了!這個不斷尋找路徑上最小MTU的過程,我們稱之為:Path MTU Discovery。
細心的觀眾會說,如果ICMP type=3 code=4 無法到達源主機會發生什麼?很顯然IP包被靜靜地丟了,TCP連接超時中斷。ICMP為什麼回不來?一般被防火牆或者路由器的訪問控制列表ACL給無情拒絕通過!如果你可以管理配置這些設備,只要允許ICMP type=3 code=4通過就可以了,否則只有老老實實關閉 Path MTU Discovery 這個功能了,至少分片可以通信,而不分片則徹底無法通信了,這就是聊勝於無,無奈的選擇!
問題有誤。
並不是只有ip層才有分片。在tcp層有mss,變身就是一種分片機制。在鏈路層也有很多協議有分片機制,例如atm
ip層做分片是2個特徵決定的: 其一,IP層是跨鏈路的通信,不同的鏈路mtu可能不同。其二,IP層轉發路徑是可能變化的。
這兩個因素導致pmtu可能很難獲得,還可能變化。而不分片就很難穿越不同的鏈路。由路由器每跳支持分片,是一個非常機智的決定。
IPv6不是沒有分片而是規定端點分片端點重組,路由器不支持分片。IPv6也想支持pmtu探測,但相信以後依賴於pmtu的方式不會廣泛應用,因為雲化會讓轉發路徑更不確定。IPv6其實是打算用1280打天下的。不好意思打擊一下其它的答案,我認為都不正確。
因為IP層分片成本最低。
1)網路現在就4層。2)物理層,MAC層分片要硬體,久了就沒人和你玩了。
3)應用層分片對於做應用的人也很痛苦。
這個完全是個軟體設計的問題,跟別的問題都沒有關係。分片是個非常複雜的邏輯,在TCP/IP協議棧裡面,IP層往下是各種各樣的數據鏈路層協議,IP層往上是各種各樣的傳輸層、應用層協議,而只有IP這一層,都統一是IP,所以在IP層實現就不需要在其他協議當中全都實現一遍了,代碼復用的效率比較高。但其實這樣的設計也給今天的網路帶來了不小的負擔,因為IP分片中不一定有完整的四層包頭,這樣給防火牆和NAT設備的實現帶來了不小的困難;另外,拆的很碎的IP分片傳輸效率也不高。最廣泛使用的TCP協議,現在其實主要是依靠傳輸層進行分片的(因為是傳輸連續的流)
我覺得和網路協議棧的設計有關係。
TCP/IP是一個分層協議,協議棧的最底層是鏈路層,接下來依次是網路層,傳輸層,應用層。
可以看見
- 鏈接層負責建立電路連接,是整個網路的物理基礎;
- 網路層負責分配地址和傳送二進位數據,主要協議是IP協議;
- ......
再來看看幾個概念
- PDU:計算機網路各層對等實體間交換的單位信息稱為協議數據單元(protocol data unit,PDU),比如分節(segment)是對應於TCP傳輸層的PDU,IP數據報(IP datagram)對應網路層實體間交換的PDU;
- SDU:按照協議與服務之間的關係,除了最低層(物理層)外,每層的PDU通過由緊鄰下層提供給本層的服務介面,作為下層的服務數據單元(service data unit,SDU)傳遞給下層,並由下層間接完成本層的PDU交換。如果本層的PDU大小超過緊鄰下層的最大SDU限制,那麼本層還要事先把PDU劃分為若干個合適的片段讓下層分開載送,再在相反方向把這些片段重組為PDU。
- 幀:鏈路層實體間交換的PDU稱為幀,其長度取決於具體的介面;
- MTU:我們進行分片的依據是MTU,而MTU是網路層和鏈路層之間的介面屬性;
我們可以很清楚的看到如果要在最低層的數據鏈路層做分片,你必須要去對不同的物理網路的驅動程序做更改; 如果要在上層的傳輸層或者應用層做分片,既然數據都要通過網路層實際上就是各協議對分片功能的重複造輪子,我們有必要付出這種成本去實現分片嗎?我想IP層就是我們在軟體設計里常用的適配層,著這裡做分片是成本最低的選擇。
是因為透明性的要求。網路的互聯互通有兩個基本的手段就是:分層和透明。透明性簡化了上層的操作,對底層的東西不需要考慮了。但要做到透明性,就要求底層有個明確的承諾,也就是介面你要確保。IP之所以能這麼流行,就是因為它的承諾是最少的:你給我什麼,我就原封不動的傳遞到目的地,當然我不保證不問題。但如果鏈路層的MTU出現了不匹配的問題,IP就比較尷尬了,不傳就違背了透明性的承諾,傳就造成複雜性增加,但早期互聯互通是首要問題,就只能硬著頭皮傳,這就通過分片來解決。現在因為互聯互通問題已經解決了,哪個還敢不支持IP啊?!而分片會導致路由器效率大降,所以基本上就不再進行分片了,而且先由運輸層發起一個端到端的MTU探測,然後以最合算的MTU進行發送。
TCP是數據傳輸協議,IP才是網路協議。數據包如何路由、分片都是網路層的範疇,當然由IP層來負責
TCP/IP協議中除了IP分片還有TCP分段,並且協議棧是優先做TCP分段,因為IP分片的處理效率是很低的。
1、TCP:TCP協議下發包,協議棧優先做TCP分段,保證ip層需要發送的數據不會因為超過MTU而做IP分片。
2、UDP:UDP協議傳輸層沒有分段的功能,只能依靠IP分片來發送較大的數據段。
往上一層TCP已經把網路抽象成端到端的位元組流了還分什麼片,往下一層有些數據鏈路層的協議對報文有長度限制,只好在IP分片啦。至於在數據鏈路層分片也不是不可以呀,那就是封裝成幀嘛,只要它的協議支持就行。
另外TCP/IP協議棧只是組網的一種方式,我的網路設備還能支持其他類型的網路呢,幹嘛非得整個分片功能照顧你。
另外IPv6已經不分片了,報文過長會被丟棄(並返回錯誤報文)——大大簡化了報文格式。
首先不都是在ip層分片的,比如tcp協議就不用再ip層分片,因為tcp層會直接分段;udp倒是數據包過大會在ip層分片。至於為什麼要這樣,其實說來說去還不是協議設計的人當初這麼想,然後就這麼做了。
層二有MTU,所以層三要分片,不是這麼簡單的原因嗎?
我覺得這個問題有點本末倒置了。
要回答為何在網路層分片,首先得回答為何網路層要分片,如果網路層不需要分片,但是它卻分片了,那才輪到為何選的是網路層。
查看各層的職責,路由和轉發的指責都落在了網路層,OSPF協議更是直接就架到了網路層上。
在網路層主要是分組交換,為了減少重發重組而對分組進行分片,這難道很難理解嗎?
IP層分片的根本原因是每一條的MTU可能不同,而不是高票答案中說的IP層分片成本最低。
@Ryane Luo 提到的"網路就4層"也有待商議,是否漏掉了第四層的傳輸層?
從實現來看,Linux中TCP/IP協議棧更偏向於直接在TCP層根據"整條鏈路的最小MSS"進行分片,因為交給IP層去分片,在發生重傳時代價是巨大的。一個IP小分片的丟失,可能導致TCP層一個大數據包的重傳。
ip虛擬網中有很多的異構網路,有不同的mtu,ip數據報要從它們中間穿梭,不分網路層pdu分誰?
推薦閱讀: