Tcp/ip 報文解析簡要介紹

在編寫網絡程序時,常使用TCP協議。那麼一個tcp包到底由哪些東西構成的呢?其實一個TCP包,首先需要通過IP協議承載,而IP報文,又需要通過以太網傳送。下面我們來看看幾種協議頭的構成。

一 .Ethernet頭

以太幀分好幾種類型,常見的以太幀爲Ethernet II

下面就是一個典型的Ethernet II幀

這裏的數據段爲TCP 、IP段數據

Ethernet II類型以太網幀的最小長度爲64字節(6+6+2+46+4),最大長度爲1518字節(6+6+2+1500+4)

首先是目的MAC 6個字節,然後源MAC6個字節,接下來數據類型兩個字節。

常見的類型如下

IPv4: 0x0800

ARP:0x0806

PPPoE:0x8864

802.1Q tag: 0x8100

IPV6: 0x86DD

MPLS Label:0x8847

然後是數據長度,46-1500字節。對於不定長的數據包,幀最後還有4個字節的FCS(Frame check sequence)

下面是一個以太幀頭示例,該報文類型爲IPv4(0x8000)

二 IP頭部

對於一個IPv4類型的以太幀,數據的開始就是IP頭部。一般IPv4的頭部是20個字節。

版本號(Version):4bit。表明IP協議的版本號。一般爲0100(IPv4),0110(IPv6)

IP包頭長度(Header Length):4bit。用於描述IP包頭長度,因爲IP包頭長度是可變的。

這裏所指示的長度,是以4個字節爲一個單位。例如,一個IP包頭的長度最長爲“1111”,即15*4=60個字節。IP包頭最小長度爲20字節。

服務類型(Type of Service):長度8比特。
IP包總長(Total Length):16bit。 以字節爲單位計算的IP包的長度 (包括頭部和數據),所以IP包最大長度65535字節。
標識符(Identifier):16bit。該字段和Flags和Fragment Offest字段聯合使用,對較大的上層數據包進行分段(fragment)操作。路由器將一個包拆分後,所有拆分開的小包被標記相同的值,以便目的端設備能夠區分哪個包屬於被拆分開的包的一部分。

標記(Flags):3bit。第一位是保留位不使用。第二位是DF(Don't Fragment)位,DF位設爲1時表明路由器不能對該數據包分包。如果一個數據包無法在不分段的情況下發送,則路由器會丟棄該數據包並返回一個錯誤信息。第三位是MF(More Fragments)位,當路由器對一個上層數據包分段,則路由器會在除了最後一個分段的IP包的包頭中將MF位設爲1。

片偏移(Fragment Offset):13bit。表示該IP包在該組分片包中位置,接收端靠此來組裝還原IP包。

生存時間(TTL):8bit。當IP包在網絡上傳送時,每經過一個路由器,TTL就自動減一。值爲0時,則丟棄報文。防止報文進入環路

協議(Protocol):8bit。標識IP頭後面的報文協議類型
以下是比較常用的協議號:

1    ICMP

2    IGMP

6    TCP

17    UDP

88    IGRP

89    OSPF

頭校驗和(Header Checksum):16bit。用來做IP頭部的正確性檢測,但不包含數據部分。由於路由器會改變TTL,所以路由器會爲每個通過的數據包重新計算這個值。

源和目的地址(Source and Destination Addresses):這兩個地段都是32比特。標識了這個IP包的起源和目標地址。要注意除非使用NAT,否則整個傳輸的過程中,這兩個地址不會改變。

下圖就是一個IP頭的內容

三 TCP 頭部

TCP封裝在IP報文中的時候,如下圖所示,TCP頭緊接着IP頭(IPV6有擴展頭的時候,則TCP頭在擴展頭後面),不攜帶選項(option)的TCP頭長爲20bytes,攜帶選項的TCP頭最長可到60bytes。

源端口(Source Port):16bit, 表示報文發送方的端口號

目的端口(Destination port): 16bit,表示報文接收方的端口號

序列號(SN):32bit,標識了TCP報文中第一個byte在對應方向的傳輸中對應的字節序號。當SYN出現,序列碼實際上是初始序列碼(ISN),而第一個數據字節是ISN+1,單位是byte。比如發送端發送的一個TCP包淨荷(不包含TCP頭)爲12byte,SN爲5,則發送端接着發送的下一個數據包的時候,SN應該設置爲5+12=17。通過系列號,TCP接收端可以識別出重複接收到的TCP包,從而丟棄重複包,同時對於亂序數據包也可以依靠系列號進行重排序,進而對高層提供有序的數據流。另外SYN標誌和FIN標誌在邏輯上也佔用一個byte,當SYN標誌位有效的時候,該字段也稱爲ISN(initial sequence number),詳細請參考後續的TCP連接管理。

應答號(ACK):32bit,標識了報文發送端期望接收的字節序列。如果設置了ACK控制位,這個值表示一個準備接收的包的序列碼,注意是準備接收的包,比如當前接收端接收到一個淨荷爲12byte的數據包,SN爲5,則發送端可能會回覆一個確認收到的數據包,如果這個數據包之前的數據也都已經收到了,這個數據包中的ACK Number則設置爲12+5=17,表示17byte之前的數據都已經收到了。在舉一個例子,如果在這個數據包之前有個SN爲3,淨荷爲2byte的數據包丟失,則在接受端接收到這個SN爲5的亂序數據包的時候,協議要求接收端必須要回復一個ACK確認包,這個確認包中的Ack Number只能設置爲3。

頭長(Header Length):4bit,指示TCP頭的長度,即數據從何處開始。最大爲15,單位是32比特,即4個字節,與IP頭中的長度定義相同。

保留(Reserved):4bit,這些位必須是0。爲了將來定義新的用途所保留,其中RFC3540將Reserved字段中的最後一位定義爲Nonce標誌。

標誌(Code Bits):8bit

CWR(Congestion Window Reduce):擁塞窗口減少標誌被髮送主機設置,用來表明它接收到了設置ECE標誌的TCP包,發送端將通過降低發送窗口的大小來降低發送速率

ECE(ECN Echo):ECN響應標誌被用來在TCP3次握手時表明一個TCP端是否具備ECN功能,並且表明接收到的TCP包的IP頭部的ECN被設置爲11。更多信息請參考RFC793。

URG(Urgent):表示緊急(The urgent pointer) 指針是否有效。

ACK(Acknowledgment):1表示這是一個確認的TCP包, 0則不是確認包。

PSH(Push):該標誌置位時,一般是表示發送端緩存中已經沒有待發送的數據,接收端不將該數據進行隊列處理,而是儘可能快將數據轉由應用處理。

RST(Reset):用於復位相應的TCP連接。通常在發生異常或者錯誤的時候會觸發復位TCP連接。

SYN(Synchronize):表示同步序列編號(Synchronize Sequence Numbers)是否有效。該標誌僅在三次握手建立TCP連接時有效。它提示TCP連接的服務端檢查序列編號,該序列編號爲TCP連接發起端(一般是客戶端)的初始序列編號。在這裏,可以把TCP序列編號看作是一個範圍從0到4,294,967,295的32位計數器。通過TCP連接交換的數據中每一個字節都經過序列編號。在TCP報頭中的序列編號欄包括了TCP分段中第一個字節的序列編號。

FIN(Finish):帶有該標誌置位的數據包用來結束一個TCP會話,但對應端口仍處於開放狀態,準備接收後續數據。當FIN標誌有效的時候我們稱呼這個包爲FIN包。

 

窗口大小(Window Size):16bit,表示從Ack Number開始還能接收多少字節的數據量,即當前接收端的接收窗口還有多少剩餘空間。用於TCP的流量控制。

校驗和(Checksum):16bit。發送端基於數據內容計算一個數值,接收端要與發送端數值結果完全一樣,才能證明數據的有效性。接收端checksum校驗失敗的時候會直接丟掉這個數據包。CheckSum是根據僞頭+TCP頭+TCP數據三部分進行計算的。

緊急指針(Urgent  Pointer):16位,在URG標誌設置了時纔有效。與序號字段的值相加後表示最後一個緊急數據的下一字節的序號,可以說這個字段是緊急指針相對當前序號的偏移。

選項(Option):長度不定,但長度必須以是32bits的整數倍。常見的選項包括MSS、SACK、Timestamp等等,後續的內容會分別介紹相關選項。

 

一個完整的TCP頭展示

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章