IP、TCP、UDP数据包长度问题
?
?IP數(shù)據(jù)包長(zhǎng)度問(wèn)題總結(jié)
首先要看TCP/IP協(xié)議,涉及到四層:鏈路層,網(wǎng)絡(luò)層,傳輸層,應(yīng)用層。
其中以太網(wǎng)(Ethernet)的數(shù)據(jù)幀在鏈路層
IP包在網(wǎng)絡(luò)層
TCP或UDP包在傳輸層
TCP或UDP中的數(shù)據(jù)(Data)在應(yīng)用層
它們的關(guān)系是 數(shù)據(jù)幀{IP包{TCP或UDP包{Data}}}
---------------------------------------------------------------------------------
在應(yīng)用程序中我們用到的Data的長(zhǎng)度最大是多少,直接取決于底層的限制。
我們從下到上分析一下:
1.在鏈路層,由以太網(wǎng)的物理特性決定了數(shù)據(jù)幀的長(zhǎng)度為(46+18)-(1500+18),其中的18是數(shù)據(jù)幀的頭和尾,也就是說(shuō)數(shù)據(jù)幀的內(nèi)容最大為1500(不包括幀頭和幀尾),即MTU(Maximum
Transmission Unit)為1500;
2.在網(wǎng)絡(luò)層,因?yàn)镮P包的首部要占用20字節(jié),所以這的MTU為1500-20=1480;
3.在傳輸層,對(duì)于UDP包的首部要占用8字節(jié),所以這的MTU為1480-8=1472;
所以,在應(yīng)用層,你的Data最大長(zhǎng)度為1472。(當(dāng)我們的UDP包中的數(shù)據(jù)多于MTU(1472)時(shí),發(fā)送方的IP層需要分片fragmentation進(jìn)行傳輸,而在接收方IP層則需要進(jìn)行數(shù)據(jù)報(bào)重 組,由于UDP是不可靠的傳輸協(xié)議,如果分片丟失導(dǎo)致重組失敗,將導(dǎo)致UDP數(shù)據(jù)包被丟棄)。
從上面的分析來(lái)看,在普通的局域網(wǎng)環(huán)境下,UDP的數(shù)據(jù)最大為1472字節(jié)最好(避免分片重組)?! ?br /> 但在網(wǎng)絡(luò)編程中,Internet中的路由器可能有設(shè)置成不同的值(小于默認(rèn)值),Internet上的標(biāo)準(zhǔn)MTU值為576,所以Internet的UDP編程時(shí)數(shù)據(jù)長(zhǎng)度最好在576-20-8=548字節(jié)以?xún)?nèi)。
---------------------------------------------------------------------------------
MTU對(duì)我們的UDP編程很重要,那如何查看路由的MTU值呢?
對(duì)于windows OS: ping -f -l 如:ping-f -l 1472 192.168.0.1
如果提示:Packets needs to be fragmented but DF set. 則表明MTU小于1500,不斷改小data_length值,可以最終測(cè)算出gateway的MTU值;
對(duì)于linux OS: ping -c -M do -s 如: ping -c 1 -M do -s 1472 192.168.0.1
如果提示 Frag needed and DF set…… 則表明MTU小于1500,可以再測(cè)以推算gateway的MTU。
---------------------------------------------------------------------------------
IP數(shù)據(jù)包的最大長(zhǎng)度是64K字節(jié)(65535),因?yàn)樵贗P包頭中用2個(gè)字節(jié)描述報(bào)文長(zhǎng)度,2個(gè)字節(jié)所能表達(dá)的最大數(shù)字就是65535。??
???
由于IP協(xié)議提供為上層協(xié)議分割和重組報(bào)文的功能,因此傳輸層協(xié)議的數(shù)據(jù)包長(zhǎng)度原則上來(lái)說(shuō)沒(méi)有限制。實(shí)際上限制還是有的,因?yàn)镮P包的標(biāo)識(shí)字段終究不可能無(wú)限長(zhǎng),按照IPv4,好像上限應(yīng)該是4G(64K*64K)。依靠這種機(jī)制,TCP包頭中就沒(méi)有“包長(zhǎng)度”字段,而完全依靠IP層去處理分幀。這就是為什么TCP常常被稱(chēng)作一種“流協(xié)議”的原因,開(kāi)發(fā)者在使用TCP服務(wù)的時(shí)候,不必去關(guān)心數(shù)據(jù)包的大小,只需講SOCKET看作一條數(shù)據(jù)流的入口,往里面放數(shù)據(jù)就是了,TCP協(xié)議本身會(huì)進(jìn)行擁塞/流量控制。??
???
UDP則與TCP不同,UDP包頭內(nèi)有總長(zhǎng)度字段,同樣為兩個(gè)字節(jié),因此UDP數(shù)據(jù)包的總長(zhǎng)度被限制為65535,這樣恰好可以放進(jìn)一個(gè)IP包內(nèi),使得 UDP/IP協(xié)議棧的實(shí)現(xiàn)非常簡(jiǎn)單和高效。65535再減去UDP頭本身所占據(jù)的8個(gè)字節(jié),UDP服務(wù)中的最大有效載荷長(zhǎng)度僅為65527(好像還要減去IP頭20個(gè)字節(jié),最后為65507)。這個(gè)值也就是
你在調(diào)用getsockopt()時(shí)指定SO_MAX_MSG_SIZE所得到返回值,任何使用SOCK_DGRAM屬性的socket,一次send的 數(shù)據(jù)都不能超過(guò)這個(gè)值,否則必然得到一個(gè)錯(cuò)誤。??
???
那么,IP包提交給下層協(xié)議時(shí)將會(huì)得到怎樣的處理呢?這就取決于數(shù)據(jù)鏈路層協(xié)議了,一般的數(shù)據(jù)鏈路層協(xié)議都會(huì)負(fù)責(zé)將IP包分割成更小的幀,然后在目的端重 組它。在EtherNet上,數(shù)據(jù)鏈路幀的大小如以上幾位大俠所言。而如果是IP?? over?? ATM,則IP包將被切分成一個(gè)一個(gè)的ATM??
Cell,大小為53字節(jié)。
******************************************************************************************************************************
******************************************************************************************************************************
??? CP提供的是一種面向連接的,可靠的字節(jié)流服務(wù),TCP提供可靠性的一種重要的方式就是MSS。通過(guò)MSS,應(yīng)用數(shù)據(jù)被分割成TCP認(rèn)為最適合發(fā)送的數(shù)據(jù) 塊,由TCP傳遞給IP的信息單位稱(chēng)為報(bào)文段或段(segment)。代表一個(gè)TCP
socket的結(jié)構(gòu)體struct tcp_sock中有多個(gè)成員用于確定應(yīng)用數(shù)據(jù)被分割成最大為多大的數(shù)據(jù)塊較為合適(最大報(bào)文段長(zhǎng)度MSS)。
??? 我們不難聯(lián)想到,跟最大報(bào)文段長(zhǎng)度最為相關(guān)的一個(gè)參數(shù)是網(wǎng)絡(luò)設(shè)備接口的MTU,以太網(wǎng)的MTU是1500,基本IP首部長(zhǎng)度為20,TCP首部是20,所以MSS的值可達(dá)1460(MSS不包括協(xié)議首部,只包含應(yīng)用數(shù)據(jù))。
??? 前面的TCP三次握手協(xié)議中我們看到,通訊的雙方都通過(guò)TCP選項(xiàng)通告了自己期望接收的MSS值,該值直接來(lái)源于struct tcp_sock的成員advmss,而這個(gè)值直接取自于網(wǎng)絡(luò)設(shè)備接口的MTU減去IP首部和TCP首部的長(zhǎng)度。在本地以太網(wǎng)中可達(dá)1460(如果首部都
不含選項(xiàng)的話(huà))。而成員rx_opt是一個(gè)結(jié)構(gòu)體struct tcp_options_received,它記錄的是來(lái)自對(duì)端的TCP選項(xiàng)通告,其成員mss_clamp表示mss的上限值,其來(lái)源就是對(duì)端的MSS通告,而mss_user是用戶(hù)設(shè)置的mss,其優(yōu)先級(jí)最高,如果有user_mss,則使用user_mss,忽略其它。
??? 從上面我們可以看到,MSS是可以通過(guò)SYN段進(jìn)行協(xié)商的(MSS選項(xiàng)只能出現(xiàn)在SYN報(bào)文段中),但它并不是任何條件下都可以協(xié)商的,如果一方不接受來(lái) 自另一方的MSS值,并且沒(méi)有user_mss,則MSS就定為默認(rèn)值536字節(jié)(加上首部,允許576字節(jié)的IP數(shù)據(jù)報(bào))。實(shí)際上,struct
tcp_sock->rx_opt->mss_clamp的初始值就定為536,等收到來(lái)自對(duì)端的MSS通告后,才進(jìn)行修改。而結(jié)構(gòu)體 struct tcp_sock的成員mss_cache用于緩存上次的有效的mss,其初始值也被定為536。
??? 函數(shù)mytcp_sync_mss為一個(gè)tcp socket中的mss相關(guān)的成員進(jìn)行數(shù)據(jù)同步,其基本的一個(gè)算法是:
??? 1、當(dāng)前的MSS正常情況下應(yīng)該為mtu-IP首部-TCP首部(不包括選項(xiàng))。
??? 2、structtcp_sock->rx_opt->mss_clamp中含有對(duì)端通告的能夠接受的MSS值,如果該值小于第一步計(jì)算所得到的MSS,則以該值為準(zhǔn)。
??? 3、IP首部如果帶有IP選項(xiàng),則MSS中要減去選項(xiàng)長(zhǎng)度。
??? 4、如果MSS已經(jīng)小于48了,則令其等于48。
??? 5、減去TCP首部中選項(xiàng)的長(zhǎng)度。
??? 6、如果MSS當(dāng)前已經(jīng)大于滑動(dòng)窗口大小的1/2,則取滑動(dòng)窗口大小的1/2作為MSS值(但不能小于48)。
??? 7、成員mss_cache用于緩存下剛剛計(jì)算所得的MSS。
??? 所以,說(shuō)本地以太網(wǎng)中MSS為1460的說(shuō)法并不正確,它還會(huì)動(dòng)態(tài)變化,如果IP首部和TCP首部中出現(xiàn)選項(xiàng),則MSS要相應(yīng)的減小,一般TCP首部中會(huì)有12字節(jié)的時(shí)間戳選項(xiàng)(外加兩字節(jié)的填充選項(xiàng)),這時(shí)的MSS就等于1448。
??? MSS的主要作用是限制另一端主機(jī)發(fā)送的數(shù)據(jù)的長(zhǎng)度,同時(shí),主機(jī)本身也控制自己發(fā)送數(shù)據(jù)報(bào)的長(zhǎng)度,這將使以較小MTU連接到一個(gè)網(wǎng)絡(luò)上的主機(jī)避免分段。
??? struct tcp_sock有一個(gè)成員xmit_size_goal,用于記錄該socket發(fā)送數(shù)據(jù)報(bào)時(shí)的segment的大小,一般情況下它的值就等于MSS(特殊情況有例外,以后再分析)。
----------------------------------------
?
以太網(wǎng)(IEEE 802.3)幀格式:
1、前導(dǎo)碼:7字節(jié)0x55,一串1、0間隔,用于信號(hào)同步
2、幀起始定界符:1字節(jié)0xD5(10101011),表示一幀開(kāi)始
3、DA(目的MAC):6字節(jié)
4、SA(源MAC):6字節(jié)
5、類(lèi)型/長(zhǎng)度:2字節(jié),0~1500保留為長(zhǎng)度域值,1536~65535保留為類(lèi)型域值(0x0600~0xFFFF)
6、數(shù)據(jù):46~1500字節(jié)
7、幀校驗(yàn)序列(FCS):4字節(jié),使用CRC計(jì)算從目的MAC到數(shù)據(jù)域這部分內(nèi)容而得到的校驗(yàn)和。
以CSMA/CD作為MAC算法的一類(lèi)LAN稱(chēng)為以太網(wǎng)。CSMA/CD沖突避免的方法:先聽(tīng)后發(fā)、邊聽(tīng)邊發(fā)、隨機(jī)延遲后重發(fā)。一旦發(fā)生沖突,必須讓每臺(tái)主機(jī)都能檢測(cè)到。關(guān)于最小發(fā)送間隙和最小幀長(zhǎng)的規(guī)定也是為了避免沖突。
考慮如下的情況,主機(jī)發(fā)送的幀很小,而兩臺(tái)沖突主機(jī)相距很遠(yuǎn)。在主機(jī)A發(fā)送的幀傳輸?shù)紹的前一刻,B開(kāi)始發(fā)送幀。這樣,當(dāng)A的幀到達(dá)B時(shí),B檢測(cè)到?jīng)_突,于是發(fā)送沖突信號(hào)。假如在B的沖突信號(hào)傳輸?shù)紸之前,A的幀已經(jīng)發(fā)送完畢,那么A將檢測(cè)不到?jīng)_突而誤認(rèn)為已發(fā)送成功。由于信號(hào)傳播是有時(shí)延的,因此檢測(cè)沖突也需要一定的時(shí)間。這也是為什么必須有個(gè)最小幀長(zhǎng)的限制。
按照標(biāo)準(zhǔn),10Mbps以太網(wǎng)采用中繼器時(shí),連接的最大長(zhǎng)度是2500米,最多經(jīng)過(guò)4個(gè)中繼器,因此規(guī)定對(duì)10Mbps以太網(wǎng)一幀的最小發(fā)送時(shí)間為51.2微秒。這段時(shí)間所能傳輸?shù)臄?shù)據(jù)為512位,因此也稱(chēng)該時(shí)間為512位時(shí)。這個(gè)時(shí)間定義為以太網(wǎng)時(shí)隙,或沖突時(shí)槽。512位=64字節(jié),這就是以太網(wǎng)幀最小64字節(jié)的原因。
512位時(shí)是主機(jī)捕獲信道的時(shí)間。如果某主機(jī)發(fā)送一個(gè)幀的64字節(jié)仍無(wú)沖突,以后也就不會(huì)再發(fā)生沖突了,稱(chēng)此主機(jī)捕獲了信道。
由于信道是所有主機(jī)共享的,如果數(shù)據(jù)幀太長(zhǎng)就會(huì)出現(xiàn)有的主機(jī)長(zhǎng)時(shí)間不能發(fā)送數(shù)據(jù),而且有的發(fā)送數(shù)據(jù)可能超出接收端的緩沖區(qū)大小,造成緩沖溢出。為避免單一主機(jī)占用信道時(shí)間過(guò)長(zhǎng),規(guī)定了以太網(wǎng)幀的最大幀長(zhǎng)為1500。
100Mbps以太網(wǎng)的時(shí)隙仍為512位時(shí),以太網(wǎng)規(guī)定一幀的最小發(fā)送時(shí)間必須為5.12μs。
1000Mbps以太網(wǎng)的時(shí)隙增至512字節(jié),即4096位時(shí),4.096μs。
*************************************
MTU的含義: MAC幀內(nèi)的數(shù)據(jù)(Payload)字段的最大長(zhǎng)度
??? 我們使用Ping命令時(shí), -l參數(shù)所指定的數(shù)據(jù)包大小,是指的ICMP報(bào)文中的ICMPData字段的長(zhǎng)度,不包括ICMPHeader,更不包括IPHeader.
以太網(wǎng)封裝IP數(shù)據(jù)包的最大長(zhǎng)度是1500字節(jié),也就是說(shuō)以太網(wǎng)最大幀長(zhǎng)應(yīng)該是以太網(wǎng)首部加上1500,再加上7字節(jié)的前導(dǎo)同步碼和1字節(jié)的幀開(kāi)始定界符,具體就是:7字節(jié)前導(dǎo)同步嗎+1字節(jié)幀開(kāi)始定界符+6字節(jié)的目的MAC+6字節(jié)的源
MAC+2字節(jié)的幀類(lèi)型+1500+4字節(jié)的FCS。
????按 照上述,最大幀應(yīng)該是1526字節(jié),但是實(shí)際上我們抓包得到的最大幀是1514字節(jié),為什么不是1526字節(jié)呢?原因是當(dāng)數(shù)據(jù)幀到達(dá)網(wǎng)卡時(shí),在物理層上網(wǎng)卡要先去掉前導(dǎo)同步碼和幀開(kāi)始定界符,然后對(duì)幀進(jìn)行CRC檢驗(yàn),如果幀校驗(yàn)和錯(cuò),就丟棄此幀。如果校驗(yàn)和正確,就判斷幀的目的硬件地址是否符合自己的接收條件(目的地址是自己的物理硬件地址、廣播地址、可接收的多播硬件地址等),如果符合,就將幀交“設(shè)備驅(qū)動(dòng)程序”做進(jìn)一步處理。這時(shí)我們的抓包軟件才能抓
到數(shù)據(jù),因此,抓包軟件抓到的是去掉前導(dǎo)同步碼、幀開(kāi)始分界符、FCS之外的數(shù)據(jù),其最大值是6+6+2+1500=1514。
???以 太網(wǎng)規(guī)定,以太網(wǎng)幀數(shù)據(jù)域部分最小為46字節(jié),也就是以太網(wǎng)幀最小是6+6+2+46+4=64。除去4個(gè)字節(jié)的FCS,因此,抓包時(shí)就是60字節(jié)。當(dāng)數(shù) 據(jù)字段的長(zhǎng)度小于46字節(jié)時(shí),MAC子層就會(huì)在數(shù)據(jù)字段的后面填充以滿(mǎn)足數(shù)據(jù)幀長(zhǎng)不小于64字節(jié)。由于填充數(shù)據(jù)是由MAC子層負(fù)責(zé),也就是設(shè)備驅(qū)動(dòng)程序。
不同的抓包程序和設(shè)備驅(qū)動(dòng)程序所處的優(yōu)先層次可能不同,抓包程序的優(yōu)先級(jí)可能比設(shè)備驅(qū)動(dòng)程序更高,也就是說(shuō),我們的抓包程序可能在設(shè)備驅(qū)動(dòng)程序還沒(méi)有填充不到64字節(jié)的幀的時(shí)候,抓包程序已經(jīng)捕獲了數(shù)據(jù)。因此不同的抓包工具抓到的數(shù)據(jù)幀的大小可能不同。下列是本人分別用wireshark和sniffer抓包的結(jié)果,對(duì)于TCP
的ACK確認(rèn)幀的大小一個(gè)是54字節(jié),一個(gè)是60字節(jié),wireshark抓取時(shí)沒(méi)有填充數(shù)據(jù)段,sniffer抓取時(shí)有填充數(shù)據(jù)段。
總結(jié)
以上是生活随笔為你收集整理的IP、TCP、UDP数据包长度问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Caffe教程:训练自己的网络结构来分类
- 下一篇: docker镜像下载的网站