鏈路層具有最大傳輸單元MTU這個(gè)特性,限制了數(shù)據(jù)幀的最大長(zhǎng)度,不同的網(wǎng)絡(luò)類型都有一個(gè)上限值妹沙。如以太網(wǎng)Ethernet II和802.3規(guī)范對(duì)幀中的數(shù)據(jù)字段長(zhǎng)度都有一個(gè)限制攻锰,其最大值分別是1500和1492個(gè)字節(jié)晾嘶。
如果IP層有數(shù)據(jù)包要傳,而且數(shù)據(jù)包的長(zhǎng)度(包括IP頭)超過了MTU娶吞,那么IP層就要對(duì)數(shù)據(jù)包進(jìn)行分片(fragmentation)操作垒迂,使每一片的長(zhǎng)度都小于或等于MTU。
MTU& MSS
這里以Ethernet II 為例妒蛇,MAC頭以下的 IP 數(shù)據(jù)報(bào)最大傳輸單位為?MTU?( Maximum Transmission Unit)机断,對(duì)于大多數(shù)使用以太網(wǎng)的局域網(wǎng)來說,MTU=1500 绣夺。
Wireshark中看以太網(wǎng)幀的封包格式為:
Frame?= Ethernet Header + IPHeader + TCP Header + TCP Segment Data
(1 )Ethernet Header =?14?Byte = Dst Physical Address (6 Byte )+? Src Physical Address (6 Byte )+ Type (2 Byte )吏奸,以太網(wǎng)幀頭以下稱之為數(shù)據(jù)幀?。
(2 )IP Header =?20?Byte (without options field )陶耍,數(shù)據(jù)在IP 層稱為?Datagram?奋蔚,分片稱為?Fragment。
( 3 ) TCP Header
=?20?Byte ( without options field)烈钞,數(shù)據(jù)在 TCP 層稱為?Stream?旺拉,分段稱為?Segment( UDP 中稱為?Message?)产上。
( 4 ) 54 個(gè)字節(jié)后為 TCP 數(shù)據(jù)負(fù)載部分( Data Portion ),即應(yīng)用層用戶數(shù)據(jù)蛾狗。
TCP分段
TCP自身支持分段晋涣,當(dāng)TCP要傳輸長(zhǎng)度超過MSS(Maxitum?Segment?Size)的數(shù)據(jù)時(shí),會(huì)先對(duì)數(shù)據(jù)進(jìn)行分段沉桌,正常情況下谢鹊,MSS小于MTU,因此留凭,TCP一般不會(huì)造成IP分片佃扼。若數(shù)據(jù)過大,只會(huì)在傳輸層進(jìn)行數(shù)據(jù)分段蔼夜,到了IP層就不用分片兼耀。因此采用TCP協(xié)議進(jìn)行數(shù)據(jù)傳輸,是不會(huì)造成IP分片的求冷。
HTTP 請(qǐng)求消息一般不會(huì)很長(zhǎng)瘤运,一個(gè)網(wǎng)絡(luò)包就能裝得下,但如果其中要提交表單
數(shù)據(jù)匠题,長(zhǎng)度就可能超過一個(gè)網(wǎng)絡(luò)包所能容納的數(shù)據(jù)量拯坟,比如在博客或者論壇上發(fā)表一篇長(zhǎng)文就屬于這種情況。這種情況下韭山,發(fā)送緩沖區(qū)中的數(shù)據(jù)就會(huì)超過 MSS 的長(zhǎng)度郁季,這時(shí)我們當(dāng)然不需要繼續(xù)等待后面的數(shù)據(jù)了。發(fā)送緩沖區(qū)中的數(shù)據(jù)會(huì)被以 MSS 長(zhǎng)度為單位進(jìn)行拆分钱磅,拆分出來的每塊數(shù)據(jù)會(huì)被放進(jìn)單獨(dú)的網(wǎng)絡(luò)包中梦裂。
根據(jù)發(fā)送緩沖區(qū)中的數(shù)據(jù)拆分的情況,當(dāng)判斷需要發(fā)送這些數(shù)據(jù)時(shí)盖淡,就在每一塊數(shù)據(jù)前面加上 TCP 頭部年柠,并根據(jù)套接字中記錄的控制信息標(biāo)記發(fā)送方和接收方的端口號(hào),然后交給 IP 模塊來執(zhí)行發(fā)送數(shù)據(jù)的操作禁舷。
TCP 數(shù)據(jù)包每次能夠傳輸?shù)淖畲髷?shù)據(jù)分段稱為?MSS?(Maxitum?Segment?Size),為了達(dá)到最佳的傳輸效能毅往,在建立 TCP 連接時(shí)雙方協(xié)商 MSS 值牵咙,雙方提供的 MSS 值的最小值為這次連接的最大 MSS 值。MSS 往往基于 MTU 計(jì)算出來攀唯,通常 MSS=MTU-sizeof(IP Header)-sizeof(TCP
Header)=1500-20-20=1460 洁桌。如
TCP segment len 指出了應(yīng)用程序數(shù)據(jù)的大小,即應(yīng)用層數(shù)據(jù)經(jīng)初次封裝后的大小侯嘀。使用wirshark看起內(nèi)容如下
POST /License/client/ProcessQueryServlet
HTTP/1.1
Host: 172.24.116.249:8050
Connection: keep-alive
Content-Length: 118
Cache-Control: max-age=0
Origin:
http://172.24.116.249:8050
Upgrade-Insecure-Requests:
1
User-Agent: Mozilla/5.0
(Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/54.0.2840.99 Safari/537.36
Content-Type:
application/x-www-form-urlencoded
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer:
http://172.24.116.249:8050/License/client/PreQueryServlet
Accept-Encoding: gzip,
deflate
Accept-Language:
zh-CN,zh;q=0.8
Cookie:
JSESSIONID=67C7292511815E7AA38CE5B863FC0E02
?
cause=&%E5%AE%A2%E6%88%B7%E5%90%8D%E7%A7%B0=kehumingcheng&%E5%AE%A2%E6%88%B7%E5%8F%B7=kehuhao&query=%E6%9F%A5%E8%AF%A2
上述請(qǐng)求頭加上body實(shí)體的長(zhǎng)度就是776bytes另凌。在nodepad中看如下
TCP/IP 可以使用一些可選參數(shù)(protocol option)谱轨,如加密等,這時(shí)頭部的長(zhǎng)度會(huì)
侵占一些MSS空間吠谢,則真正用來承載數(shù)據(jù)的就剩下1500-20-20-12=1448字節(jié)了土童。如
IP分片
???????? Tcp建立連接的時(shí)候,必須進(jìn)行三次握手工坊,在前兩個(gè)握手包中献汗,雙方互相聲明了自己的MSS。經(jīng)過握手后王污,彼此知道自己的MSS罢吃,就會(huì)自動(dòng)調(diào)整從而適配接收方的MTU。如一個(gè)IP包最多可以攜帶1500-20=1480字節(jié)的數(shù)據(jù)昭齐。當(dāng)要傳輸?shù)臄?shù)據(jù)塊大于1460字節(jié)時(shí)尿招,TCP層就會(huì)把它分段,封裝成多個(gè)網(wǎng)絡(luò)包阱驾。這樣就谜,數(shù)據(jù)經(jīng)過本地 TCP 層分段后,交給本地 IP 層啊易,在本地 IP 層就不需要分片了吁伺。
?????? 從這一層意義上說,其實(shí)TCP無所謂分段租谈,因?yàn)槊總€(gè)TCP數(shù)據(jù)報(bào)在組成前其大小就已經(jīng)被MSS限制了篮奄,所以TCP數(shù)據(jù)報(bào)的長(zhǎng)度是不可能大于MSS的,自然到了IP層的數(shù)據(jù)報(bào)肯定不會(huì)超過MTU割去,當(dāng)然也就不用分片了窟却。
然而,如果網(wǎng)絡(luò)上有交換機(jī)之類的MTU比發(fā)送方和接收方都小呻逆,則還會(huì)有問題夸赫。實(shí)際上,在下一跳路由( Next Hop )的鄰居路由器上可能發(fā)生 IP 分片咖城。因?yàn)槁酚善鞯木W(wǎng)卡的MTU 可能小于需要轉(zhuǎn)發(fā)的 IP 數(shù)據(jù)報(bào)的大小茬腿。這時(shí)候,在路由器上可能發(fā)生兩種情況:
( 1 )如果源發(fā)送端設(shè)置了這個(gè) IP 數(shù)據(jù)包可以分片( May
Fragment 宜雀, DF=0 )切平,路由器將 IP 數(shù)據(jù)報(bào)分片后轉(zhuǎn)發(fā)。
( 2 )如果源發(fā)送端設(shè)置了這個(gè) IP 數(shù)據(jù)報(bào)不可以分片( Don’t
Fragment 辐董, DF=1 )悴品,路由器將 IP 數(shù)據(jù)報(bào)丟棄,并發(fā)送 ICMP 分片錯(cuò)誤消息給源發(fā)送端。
而對(duì)于UDP數(shù)據(jù)報(bào)和ICMP苔严,如果組成的 IP數(shù)據(jù)報(bào)長(zhǎng)度超過了1500定枷,那么IP數(shù)據(jù)報(bào)顯然就要進(jìn)行分片,因?yàn)樗鼈儾荒芟馮CP一樣自己進(jìn)行分段届氢。
UDP和ICMP認(rèn)為網(wǎng)絡(luò)層可以傳輸無限長(zhǎng)(實(shí)際上有65535的限制)的數(shù)據(jù)欠窒,當(dāng)這兩種協(xié)議發(fā)送數(shù)據(jù)時(shí),它們不考慮數(shù)據(jù)長(zhǎng)度悼沈,僅在其頭部添加UDP或ICMP首部贱迟,然后直接交給網(wǎng)絡(luò)層就萬事大吉了。接著網(wǎng)絡(luò)層IP協(xié)議對(duì)這種“身長(zhǎng)頭短”的數(shù)據(jù)進(jìn)行分片絮供,不要指望IP能很“智能”地識(shí)別傳給它的數(shù)據(jù)上層頭部在哪里衣吠,載荷又在哪里,它會(huì)直接將整個(gè)的數(shù)據(jù)切成N個(gè)分片壤靶,這樣做的結(jié)果是缚俏,只有第一個(gè)分片具有UDP或者ICMP首部,而其它分片則沒有贮乳。因此UDP不會(huì)分段忧换,而是由IP來分。
一般IP首部為20字節(jié)向拆,UDP或ICMP首部為8字節(jié)亚茬,數(shù)據(jù)的凈荷(payload)部分預(yù)留是1500-20-8=1472字節(jié)。如果數(shù)據(jù)靜荷載部分大于1472字節(jié)浓恳,就會(huì)出現(xiàn)分片現(xiàn)象刹缝。
?????? 以ping 一個(gè)大包 1473字節(jié)為例,
icmp包頭位于第一個(gè)分片中颈将,其余分片只包含ip頭和數(shù)據(jù)梢夯。除了最后一個(gè)分片,其它分片的數(shù)據(jù)(除去ip頭)必須是8的整數(shù)倍晴圾。
第一個(gè)分片包的有效載荷為:1514-14-20-8=1472颂砸,第二個(gè)分片包的有效載荷為:35-14-20=1,可見1473大小的數(shù)據(jù)被分在了兩個(gè)包里面進(jìn)行傳輸死姚。