TCP/IP協議棧中各層包頭的分析
Protocol列表示的是該數據包最高層對應的協議,Length列表示該包的長度(包括從底層的協議到最高層的協議,其中包頭一般是,鏈路層14字節,IP20字節,TCP20字節)
1、獲取數據包
(a) 以“DIY_DE2之DM9000A網卡調試系列例程(二)——DM9000A測試、自收發、實現UDP”為實例
獲取數據包的方式有兩種:通過wireshark抓包工具抓取數據包和通過NIOS II端中斷的方式獲取PC端發送的數據包,獲取的數據包分別如下:
通過wireshark獲得:
e0 cb 4e b7 9e d1 01 60
6e 11 02 0f 08 00 45 00
05 d8 00 00 00 00 80 11
b1 97 c0 a8 00 2c c0 a8
02 01 04 00 04 00 05 c4
00 00
這42個字節即是該例程的數據發送到PC端的包頭,42個字節之后就是有效數據,最后的4個字節則為校驗位。通過上述例程語句也能很清楚的分析各個數據的含義。
通過NIOS II端獲得:
ff ff ff ff ff ff e0 cb
4e b7 9e d1 08 00 45 00
00 1e 3c ac 00 00 80 11
3b 7a c0 a8 02 01 ff ff
ff ff 04 00 04 00 00 0a
04 31
同上。
由於該例程主要是實現UDP,所以TCP包頭不夠明了,為了全面的分析各個包頭,將使用下面的例程。
(b) 以“DIY_DE2之DM9000A網卡調試系列例程(四)——基於NicheStack協議棧的TCP/IP實現”為實例
通過wireshark獲取的數據包如下:
00 07 ed ff 06 00 00 0f
ea fd 9f 96 08 00 45 00
00 29 38 13 40 00 40 06
7d 60 c0 a8 02 0a c0 a8
02 01 18 98 00 17 37 8d
49 3b 00 46 74 e0 50 18
fe d9 ea f7 00 00 32
下面將對其做具體分析。
2、MAC包頭
MAC包頭占有14字節,即:
00 07 ed ff 06 00 00 0f ea fd 9f 96 08 00
很容易看出來 00 07 ed ff 06 00 和 00 0f ea fd 9f 96 分別是DIY_DE2和PC的MAC地址,后面的 08 00,不知道是什么。
3、IP包頭
IP包頭占有20個字節,即:
45 00 00 29 38 13 40 00 40 06 7d 60 c0 a8 02 0a c0 a8 02 01
(1) “45”,其中“4”是IP協議的版本(Version),說明是IP4。“5”是IHL位,表示IP頭部的長度,是一個4bit字段,最大就是1111了,值為12,IP頭部的最大長度就是60字節。而這里為“5”,說明是20字節,這是標准的IP頭部長度,頭部報文中沒有發送可選部分數據。
(2) “00”,服務類型(Type of Service)。這個8bit字段由3bit的優先權子字段(現在已經被忽略),4 bit的TOS子字段以及1 bit的未用字段(現在為0)構成.4 bit的TOS子字段包含:最小延時、最大吞吐量、最高可靠性以及最小費用構成,這四個1bit位最多只能有一個為1,本例中都為0,表示是一般服務。
(3) “00 29”,IP數據報文總長,包含頭部以及數據,這里表示41字節。這41字節由20字節的IP頭部以及21字節的TCP頭構成(最后的一個字節為數據)。因此目前最大的IP數據包長度是65535字節。
(4) “38 13”,兩個字節的標志位,這個是讓目的主機來判斷新來的分段屬於哪個分組。
(5) “40”,轉換為二進制就是“0100 0000”,其中第一位是IP協議目前沒有用上的,為0。接着的是兩個標志DF和MF。DF為1表示不要分段,MF為1表示還有進一步的分段(本例為0)。然后的“0 0000”是分段便移(Fragment Offset)。
(6) “00”,待定。
(7) “40”這個字節就是TTL(Time To Live)了,表示一個IP數據流的生命周期,用Ping顯示的結果,能得到TTL的值,很多文章就說通過TTL位來判別主機類型。因為一般主機都有默認的TTL值,不同系統的默認值不一樣。比如WINDOWS為128。不過,一般Ping得到的都不是默認值,這是因為每次IP數據包經過一個路由器的時候TTL就減一,當減到0時,這個數據包就消亡了。這也時Tracert的原理。本例中為“40”,轉換為十進制就是64了,我用的WinXP。
(8) “06”,這個字節表示傳輸層的協議類型(Protocol)。在RFC790中有定義,6表示傳輸層是TCP協議。
(9) “7d 60”這個16bit是頭校驗和(Header Checksum)。
(10) “c0 a8 02 0a”,這個是源地址,也就是PC的IP地址,轉換為十進制的IP地址就是:192.168.2.10。
(11) “c0 a8 02 01”,這個是目標地址,也就是DIY_DE2的地址,轉換為十進制的IP地址就是:192.168.2.1。
4、TCP包頭
TCP包頭占有20個字節,即:
18 98 00 17 37 8d 49 3b 00 46 74 e0 50 18 fe d9 ea f7 00 00
(1) “18 98”,表示本地端口號,轉換為十進制就是3368。
(2) “00 15”,表示目標端口號,轉換為十進制就是23,因為我是連接TELNET站點,所以,這個就是23。
(3) “37 8d 49 3b”,是順序號(Sequence Number),簡寫為SEQ。
(4) “00 46 74 e0”,是確認號(Acknowledgment Number),簡寫為ACKNUM。
(5) “50 18”,轉換為二進制,“0101 0000 0001 1000”。這兩個字節,總共16bit,有好多東西。第一個4bit“0101”,是TCP頭長,十進制為5,表示20個字節。接着的6bit現在TCP協議沒有用上,都為0。最后的6bit“01 1000”是六個重要的標志。這是兩個計算機數據交流的信息標志。接收和發送斷根據這些標志來確定信息流的種類。下面是一些介紹:
URG:(Urgent Pointer field significant)緊急指針。用到的時候值為1,用來處理避免TCP數據流中斷。
ACK:(Acknowledgment fieldsignificant)置1時表示確認號(AcknowledgmentNumber)為合法,為0的時候表示數據段不包含確認信息,確認號被忽略。
PSH:(Push Function),PUSH標志的數據,置1時請求的數據段在接收方得到后就可直接送到應用程序,而不必等到緩沖區滿時才傳送。
RST:(Reset the connection)用於復位因某種原因引起出現的錯誤連接,也用來拒絕非法數據和請求。如果接收到RST位時候,通常發生了某些錯誤。
SYN:(Synchronize sequence numbers)用來建立連接,在連接請求中,SYN=1,ACK=0,連接響應時,SYN=1,ACK=1。即,SYN和ACK來區分Connection Request和Connection Accepted。
FIN:(No more data from sender)用來釋放連接,表明發送方已經沒有數據發送了。
這6個標志位,對號入座。本例中SYN=0,ACK=1,當然就是表示連接請求了。在分析TCP包頭時候,要注意這兩位的變換。
(6) “fe d9”,窗口值,用來控制實現流量控制。
(7) “ea f7”,檢驗和,TCP的檢驗和是強制的。
(8) “00 00”,緊急指針。
TCP包頭格式詳解
一般來說,網絡編程我們只需要調用一些封裝好的函數或者組件就能完成大部分的工作,但是一些特殊的情況下,就需要深入的理解
網絡數據包的結構,以及協議分析。如:網絡監控,故障排查等……
IP包是不安全的,但是它是互聯網的基礎,在各方面都有廣泛的應用。由IP協議衍生的協議族有10數種(據我所知),以后還會出現
更多的基於IP的協議…
先從實際出發吧!
一般我們在談上網速度的時候,專業上用帶寬來描述,其實無論說網速或者帶寬都是不准確的,呵呵。比如:1兆,512K……
有些在學校的學生,也許會有疑問,明明我的業務是1M,為什么下載速度到100K就飆不上去了?512K的為什么50多K就封頂了?…
這里所說的1M是指1Mbps = 1 Million Bits Per Second,也就是1M比特每秒,即一秒鍾傳輸1048576個二進制位。我們知道一個字節
是8個二進制位。
好,又來問題了。即便這樣子,1M=1048756÷8=131072÷1024=128K。那也應該有128K啊,為什么下載速度還是很少到120K,
110K都謝天謝地了。看完本文,你的帳就對了……
IP數據包結構:
如圖,一個刻度表示1個二進制位(比特)。
1-1.版本4位,表示版本號,目前最廣泛的是4=B1000,即常說的IPv4;相信IPv6以后會廣泛應用,它能給世界上每個紐扣都分配
一個IP地址。
1-2.頭長4位,數據包頭部長度。它表示數據包頭部包括多少個32位長整型,也就是多少個4字節的數據。無選項則為5(紅色部分)。
1-3.服務類型,包括8個二進制位,每個位的意義如下:
過程字段:3位,設置了數據包的重要性,取值越大數據越重要,取值范圍為:0(正常)~ 7(網絡控制)
延遲字段:1位,取值:0(正常)、1(期特低的延遲)
流量字段:1位,取值:0(正常)、1(期特高的流量)
可靠性字段:1位,取值:0(正常)、1(期特高的可靠性)
成本字段:1位,取值:0(正常)、1(期特最小成本)
保留字段:1位 ,未使用
1-4.包裹總長16位,當前數據包的總長度,單位是字節。當然最大只能是65535,及64KB。
2-1.重組標識16位,發送主機賦予的標識,以便接收方進行分片重組。
2-2.標志3位,他們各自的意義如下:
保留段位(2):1位,未使用
不分段位(1):1位,取值:0(允許數據報分段)、1(數據報不能分段)
更多段位(0):1位,取值:0(數據包后面沒有包,該包為最后的包)、1(數據包后面有更多的包)
2-3.段偏移量13位,與更多段位組合,幫助接收方組合分段的報文,以字節為單位。
3-1.生存時間8位,經常ping命令看到的TTL(Time To Live)就是這個,每經過一個路由器,該值就減一,到零丟棄。
3-2.協議代碼8位,表明使用該包裹的上層協議,如TCP=6,ICMP=1,UDP=17等。
3-3.頭檢驗和16位,是IPv4數據包頭部的校驗和。
4-1.源始地址,32位4字節,我們常看到的IP是將每個字節用點(.)分開,如此而已。
5-1.目的地址,32位,同上。
6-1.可選選項,主要是給一些特殊的情況使用,往往安全路由會當作攻擊而過濾掉,普聯(TP_LINK)的TL-ER5110路由就能這么做。
7-1.用戶數據。
TCP數據包結構:
1-1.源始端口16位,范圍當然是0-65535啦。
1-2.目的端口,同上。
2-1.數據序號32位,TCP為發送的每個字節都編一個號碼,這里存儲當前數據包數據第一個字節的序號。
3-1.確認序號32位,為了安全,TCP告訴接受者希望他下次接到數據包的第一個字節的序號。
4-1.偏移4位,類似IP,表明數據距包頭有多少個32位。
4-2.保留6位,未使用,應置零。
4-3.緊急比特URG—當URG=1時,表明緊急指針字段有效。它告訴系統此報文段中有緊急數據,應盡快傳送(相當於高優先級的數據)。
4-3.確認比特ACK—只有當ACK=1時確認號字段才有效。當ACK=0時,確認號無效。參考TCP三次握手
4-4.復位比特RST(Reset) —當RST=1時,表明TCP連接中出現嚴重差錯(如由於主機崩潰或其他原因),必須釋放連接,然后再重新
建立運輸連接。參考TCP三次握手
4-5.同步比特SYN—同步比特SYN置為1,就表示這是一個連接請求或連接接受報文。參考TCP三次握手
4-6.終止比特FIN(FINal)—用來釋放一個連接。當FIN=1時,表明此報文段的發送端的數據已發送完畢,並要求釋放運輸連接。
4-7.窗口字段16位,窗口字段用來控制對方發送的數據量,單位為字節。TCP連接的一端根據設置的緩存空間大小確定自己的接收窗口
大小,然后通知對方以確定對方的發送窗口的上限。
5-1.包校驗和16位,包括首部和數據這兩部分。在計算檢驗和時,要在TCP報文段的前面加上12字節的偽首部。
5-2.緊急指針16位,緊急指針指出在本報文段中的緊急數據的最后一個字節的序號。
6-1.可選選項24位,類似IP,是可選選項。
6-2.填充8位,使選項湊足32位。
7-1.用戶數據……
可以看出,每個IP包至少要20字節的頭部長度,這些與下載內容無關,加上目前多數傳輸,包括http協議(就是IE直接下載),都是基於
TCP協議的,所以IP包裹還要從用戶數據中扣除20字節的TCP包頭,這里已經是40字節,加上其他程序的連接,狀態確認等等包裹,因
而算出來要比理論值要小。
另外網絡環境(包括穩定因素和傳輸節點的轉發率)也是影響下載速度的重要原因…