TCP和1448
1448字節(jié)是實際場景下,單個TCP包的實際運載能力。也就是說,實際場景下,上層調用send(1000KB),下層會把這1000KB封裝成多個TCP包進行發(fā)送。單個TCP包每次打包1448字節(jié)的數(shù)據(jù)進行發(fā)送。
詳細的TCP在傳輸情景wireshark截圖如圖1
圖1
每個TCP包在理論上應該能打包更多數(shù)據(jù)才對,但是實際場景下TCP傳輸為什么會以這個1448作為打包單位呢?
這個實際TCP單包傳輸1448字節(jié)數(shù)據(jù)的根源在于“以太網Ethernet最大的數(shù)據(jù)幀是1518字節(jié)”。
1500字節(jié)的MTU
以太網Ethernet最大的數(shù)據(jù)幀是1518字節(jié)。以太網幀的幀頭14字節(jié)和幀尾CRC校驗4字節(jié)(共占18字節(jié)),剩下承載上層協(xié)議的地方也就是Data域最大就只剩1500字節(jié). 這個值我們就把它稱之為MTU。
我們來看看linux上MTU默認值,查證一下,cat /sys/class/net/eth0/mtu
這個MTU值可以修改,但是現(xiàn)在大部分計算機網絡都被以太網承載,所以修改這個值沒有什么實際意義。
MSS決定TCP的單包傳輸量
MSS就是TCP數(shù)據(jù)包每次能夠傳輸?shù)淖畲罅?。為了達到最佳的傳輸效能,TCP協(xié)議在建立連接的時候通常要協(xié)商雙方的MSS值,這個值TCP協(xié)議在實現(xiàn)的
時候往往用MTU值代替(需要減去IP數(shù)據(jù)包包頭的大小20Bytes和TCP數(shù)據(jù)段的包頭20Bytes)所以往往MSS為1460(如圖1中紅色方框所示的SYN包中的MSS值)。通訊雙方會根據(jù)雙方提供的MSS值得最小值確定為這次連接的最大MSS值。
MSS為1460是由1500-20(IP頭)-20(TCP頭)計算出的。
實際場景下,TCP包頭中會帶有12字節(jié)的選項----時間戳。
這樣,單個TCP包實際傳輸?shù)淖畲罅烤涂s減為1448字節(jié)。1448=1500-20(IP頭)-32(20字節(jié)TCP頭和12字節(jié)TCP選項時間戳)
回到我們開篇的問題
“每個TCP包在理論上應該能打包更多數(shù)據(jù)才對,但是實際場景下TCP傳輸為什么會以這個1448作為打包單位呢?”
理論上,單個TCP包能打包的數(shù)據(jù)量遠遠多于1448字節(jié),現(xiàn)在為了適應MTU,只要在以太網上跑TCP,系統(tǒng)就默認最大以1448字節(jié)打包TCP。
假如我們用更大的數(shù)據(jù)量來打包會有什么結果呢?
答案是降低了傳輸效率。
超過MTU的大包反而降低效率的原因如下:
IP層非常關心MTU,因為IP層會根據(jù)MTU來決定是否把上層傳下來的數(shù)據(jù)進行分片。就像一條運輸線路的承載能力是有限的,碰到大東西要運輸,只能把大東西拆開成為散件,分開運輸,到達目的地之后還必須能再次組裝起來。
當兩臺遠程PC互聯(lián)的時候,它們的數(shù)據(jù)需要穿過很多的路由器和各種各樣的網絡媒介才能到達對端,網絡中不同媒介的MTU各不相同,就好比一長段的水管,由不同粗細的水管組成(MTU不同 :))通過這段水管最大水量就要由中間最細的水管決定。
對于網絡層的上層協(xié)議而言(我們以TCP/IP協(xié)議族為例)它們對水管粗細不在意它們認為這個是網絡層的事情。網絡層IP協(xié)議會檢查每個從上層協(xié)議下來的數(shù)據(jù)包的大小,并根據(jù)本機MTU的大小決定是否作“分片”處理。分片最大的壞處就是降低了傳輸性能,本來一次可以搞定的事情,分成多次搞定,所以在網絡層更高一層(就是傳輸層)的實現(xiàn)中往往會對此加以注意!
這個就是在以太網上,TCP不發(fā)大包,反而發(fā)送1448小包的原因。只要這個值TCP才能對鏈路進行效能最高的利用。
|