1. 程式人生 > >MAC/IP/TCP/UDP頭結構分析

MAC/IP/TCP/UDP頭結構分析

相關索引:https://blog.csdn.net/knowledgebao/article/details/84626184


目錄

一、MAC幀頭定義

二、IP頭結構的定義

三、TCP頭結構定義

四、UDP頭結構的定義


一、MAC幀頭定義

MAC幀是資料幀的一種。而所謂資料幀,就是資料鏈路層協議資料單元,它包括三部分:幀頭,資料部分,幀尾。其中,幀頭和幀尾包含一些必要的控制資訊,比如同步資訊、地址資訊、差錯控制資訊等;資料部分則包含網路層傳下來的資料,比如ip資料包。

目前,有四種不同格式的乙太網幀在使用,它們分別是:

  1. Ethernet II即DIX 2.0:Xerox與DEC、Intel在1982年制定的乙太網標準幀格式。Cisco名稱為:ARPA。
  2. Ethernet 802.3 raw:Novell在1983年公佈的專用乙太網標準幀格式。Cisco名稱為:Novell-Ether。
  3. Ethernet 802.3 SAP:IEEE在1985年公佈的Ethernet 802.3的SAP版本乙太網幀格式。Cisco名稱為:SAP。
  4. Ethernet 802.3 SNAP:IEEE在1985年公佈的Ethernet 802.3的SNAP版本乙太網幀格式。Cisco名稱為:SNAP。

Ethernet II和IEEE802.3的幀格式比較類似,主要的不同點在於前者定義的2位元組為包型別,而後者定義的2位元組為的長度;所幸的是,後者定義的有效長度值與前者定義的有效型別值無一相同,這樣就容易區分兩種幀格式了。如果值大於 1500(0x05DC),說明是乙太網型別欄位,EthernetII 幀格式。如果值小於等於1500,說明是長度欄位,IEEE802.3 幀格式。

因此型別欄位值最小的是 0x0600。而長度最大為 1500。

   MAC層要求定界字元之後的內容要在64位元組到1518個位元組之間,其中包括14位元組的目標和源MAC,4位元組的CRC32值。並且報文幀之間的傳遞間隔要大於9.6us。

 

型別欄位 (2個位元組): 用來標誌上一層使用的是什麼協議,以便把收到的MAC幀的資料上交給上一層的這個協議;資料欄位 (46-1500): 正式名稱是MAC客戶資料欄位最小長度64 位元組-18位元組的首部和尾部 = 資料欄位的最小長度;FCS欄位 (4 位元組):當資料欄位的長度小於 46 位元組時,應在資料欄位的後面加入整數字節的填充欄位,以保證乙太網的MAC幀長不小於64 位元組;在幀的前面插入的 8 位元組中的第一個欄位共 7 個位元組,是前同步碼,用來迅速實現 MAC幀的位元同步。第二個欄位是幀開始定界符,表示後面的資訊就是MAC幀。

/*資料幀定義,頭14個位元組,尾4個位元組*/
typedef struct _MAC_FRAME_HEADER
{
 char m_cDstMacAddress[6];    //目的mac地址
 char m_cSrcMacAddress[6];    //源mac地址
 short m_cType;            //上一層協議型別,如0x0800代表上一層是IP協議,0x0806為arp
}__attribute__((packed))MAC_FRAME_HEADER,*PMAC_FRAME_HEADER;

typedef struct _MAC_FRAME_TAIL
{
 unsigned int m_sCheckSum;    //資料幀尾校驗和
}__attribute__((packed))MAC_FRAME_TAIL, *PMAC_FRAME_TAIL;

二、IP頭結構的定義

/*IP頭定義,共20個位元組*/
typedef struct _IP_HEADER 
{
 char m_cVersionAndHeaderLen;       //版本資訊(前4位),頭長度(後4位)
 char m_cTypeOfService;            // 服務型別8位
 short m_sTotalLenOfPacket;        //資料包長度
 short m_sPacketID;              //資料包標識
 short m_sSliceinfo;               //分片使用
 char m_cTTL;                  //存活時間
 char m_cTypeOfProtocol;          //協議型別
 short m_sCheckSum;             //校驗和
 unsigned int m_uiSourIp;          //源ip
 unsigned int m_uiDestIp;          //目的ip
} __attribute__((packed))IP_HEADER, *PIP_HEADER ;
  • 版本(Version)欄位:佔4位元。用來表明IP協議實現的版本號,當前一般為IPv4,即0100。
  • 報頭長度(Internet Header Length,IHL)欄位:佔4位元。因為頭部長度不固定(Option可選部分不固定),所以需要標識該分組的頭部長度多少,用4bit表示,以4byte為單位,取值範圍:5-15,即20(5*4)-60(15*4)byte(其他欄位也是類似的計算方式,因為bit位是不夠表示該欄位的值) 
  • 服務型別(Type of Service ,TOS)欄位:佔8位元。其中前3位元為優先權子欄位(Precedence,現已被忽略)。第8位元保留未用。第4至第7位元分別代表延遲、吞吐量、可靠性和花費。當它們取值為1時分別代表要求最小時延、最大吞吐量、最高可靠性和最小費用。這4位元的服務型別中只能置其中1位元為1。可以全為0,若全為0則表示一般服務。服務型別欄位聲明瞭資料報被網路系統傳輸時可以被怎樣處理。例如:TELNET協議可能要求有最小的延遲,FTP協議(資料)可能要求有最大吞吐量,SNMP協議可能要求有最高可靠性,NNTP(Network News Transfer Protocol,網路新聞傳輸協議)可能要求最小費用,而ICMP協議可能無特殊要求(4位元全為0)。實際上,大部分主機會忽略這個欄位,但一些動態路由協議如OSPF(Open Shortest Path First Protocol)、IS-IS(Intermediate System to Intermediate System Protocol)可以根據這些欄位的值進行路由決策。RFC2474的ToS取消了IP precedence欄位而使用了DSCP,QoS裡有描述,給QoS用來打標籤。TOS欄位歷史:
  • 總長度欄位:佔16位元。指明整個資料報的長度(以位元組為單位,含頭長度)。最大長度為65535位元組。可用總長度減去頭部長度獲得實際報文資料的長度,取值範圍0-65535byte,鏈路只允許1500byte,所以一般都需要MTU分片 。
  • 標誌欄位:佔16位元。用來唯一地標識主機發送的每一份資料報。通常每發一份報文,它的值會加1。通常與標記欄位和分片偏移欄位一起用於IP報文的分片。當原始報文大小超過MTU,那麼就必須將原始資料進行分片。每個被分片的報文大小不得超過MTU,而這個欄位還將在同一原始檔案被分片的報文上打上相同的標記,以便接收裝置可以識別出屬於同一個報文的分片,“類似於程序號”,有時候電信會用他來識別流量是否是同一臺主機(因為做了PAT後源ip都是一樣的,雞賊!)

    注意:Ethernet乙太網跟802.3乙太網有所區別,802.3是由IEEE指定的標準,比較複雜用的比較少,網絡卡一般兩種都支援。IP資料包的MTU值在各種物理線路環境下對應的MTU取值:(注意:不包含幀頭和尾)

  • 標誌位欄位:佔3位元。標誌一份資料報是否要求分段。第1位沒有被使用。第2位D是不分片位(DF),Do not fragment,顧名思義,不要分片,當DF位設定為1時,表示路由器不能對報文進行分片處理。第3位M表示還有後繼分片(MF),More fragment,多分片,當路由器對報分進行分片時,除了最後一個分片的MF位設定為0外,其他所有分片的MF位均設定1,以便接收者直到收到MF位為0的分片為止

  • 段偏移欄位:佔13位元。如果一份資料報要求分段的話,此欄位指明該段偏移距原始資料報開始的位置。
  • 生存期(TTL:Time to Live)欄位:佔8位元。用來設定資料報最多可以經過的路由器數。由傳送資料的源主機設定,通常為32、64(win7)、128、255(linux)等。每經過一個路由器,其值減1,直到0時該資料報被丟棄。
  • 協議欄位:佔8位元。指明IP層所封裝的上層協議型別,如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)等。
  • 頭部校驗和欄位:佔16位元。內容是根據IP頭部計算得到的校驗和碼。計算方法是:對頭部中每個16位元進行二進位制反碼求和。(和ICMP、IGMP、TCP、UDP不同,IP不對頭部後的資料進行校驗)。
  • 源IP地址、目標IP地址欄位:各佔32位元。用來標明發送IP資料報文的源主機地址和接收IP報文的目標主機地址。
  • 可選項欄位:佔32位元。用來定義一些任選項:如記錄路徑、時間戳等。這些選項很少被使用,同時並不是所有主機和路由器都支援這些選項。可選項欄位的長度必須是32位元的整數倍,如果不足,必須填充0以達到此長度要求。

三、TCP頭結構定義

/*TCP頭定義,共20個位元組*/
typedef struct _TCP_HEADER 
{
 short m_sSourPort;              // 源埠號16bit
 short m_sDestPort;              // 目的埠號16bit
 unsigned int m_uiSequNum;         // 序列號32bit
 unsigned int m_uiAcknowledgeNum;  // 確認號32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP頭長度;中6位:保留;後6位:標誌位
 short m_sWindowSize;            // 視窗大小16bit
 short m_sCheckSum;              // 檢驗和16bit
 short m_surgentPointer;           // 緊急資料偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
/*TCP頭中的選項資料部分定義
kind = 1表示 無操作NOP,無後面的部分
kind = 2表示 maximum segment,後面的Length就是maximum segment選項的長度(以byte為單位,1+1+內容部分長度)
kind =  3表示 windows scale,後面的Length就是 windows scale選項的長度(以byte為單位,1+1+內容部分長度)
kind =  4表示 SACK permitted    Length為2,沒有內容部分
kind =  5表示這是一個SACK包     Length為2,沒有內容部分
kind =  8表示時間戳,Length為10,含8個位元組的時間戳
*/
typedef struct _TCP_OPTIONS
{
 char m_ckind;            //kind(8bit)
 char m_cLength;          //Length(8bit,整個選項的長度,包含前兩部分)
 char m_cContext[32];     //內容(如果有的話)
}__attribute__((packed))TCP_OPTIONS, *PTCP_OPTIONS;
  • 源埠:源埠和IP地址的作用是標識報文的返回地址。
  • 目的埠:埠指明接收方計算機上的應用程式介面。TCP報頭中的源埠號和目的埠號同IP資料報中的源IP與目的IP唯一確定一條TCP連線。
  • 序號和確認號:是TCP可靠傳輸的關鍵部分。序號是本報文段傳送的資料組的第一個位元組的序號。在TCP傳送的流中,每一個位元組一個序號。e.g.一個報文段的序號為300,此報文段資料部分共有100位元組,則下一個報文段的序號為400。所以序號確保了TCP傳輸的有序性。確認號,即ACK,指明下一個期待收到的位元組序號,表明該序號之前的所有資料已經正確無誤的收到。確認號只有當ACK標誌為1時才有效。比如建立連線時,SYN報文的ACK標誌位為0。
  • 資料偏移/首部長度:4bits。由於首部可能含有可選項內容,因此TCP報頭的長度是不確定的,報頭不包含任何任選欄位則長度為20位元組,4位首部長度欄位所能表示的最大值為1111,轉化為10進製為15,15*32/8 = 60,故報頭最大長度為60位元組。首部長度也叫資料偏移,是因為首部長度實際上指示了資料區在報文段中的起始偏移值。
  • 保留:為將來定義新的用途保留,現在一般置0。
  • 控制位:URG  ACK  PSH  RST  SYN  FIN,共6個,每一個標誌位表示一個控制功能。
  1.  URG:緊急指標標誌,為1時表示緊急指標有效,為0則忽略緊急指標。
  2.  ACK:確認序號標誌,為1時表示確認號有效,為0表示報文中不含確認資訊,忽略確認號欄位。
  3.  PSH:push標誌,為1表示是帶有push標誌的資料,指示接收方在接收到該報文段以後,應儘快將這個報文段交給應用程式,而不是在緩衝區排隊。
  4.  RST:重置連線標誌,用於重置由於主機崩潰或其他原因而出現錯誤的連線。或者用於拒絕非法的報文段和拒絕連線請求。
  5.  SYN:同步序號,用於建立連線過程,在連線請求中,SYN=1和ACK=0表示該資料段沒有使用捎帶的確認域,而連線應答捎帶一個確認,即SYN=1和ACK=1。
  6.  FIN:finish標誌,用於釋放連線,為1時表示傳送方已經沒有資料傳送了,即關閉本方資料流。
  • 視窗:滑動視窗大小,用來告知傳送端接受端的快取大小,以此控制傳送端傳送資料的速率,從而達到流量控制。視窗大小時一個16bit欄位,因而視窗大小最大為65535。
  • 校驗和:奇偶校驗,此校驗和是對整個的 TCP 報文段,包括 TCP 頭部和 TCP 資料,以 16 位字進行計算所得。由傳送端計算和儲存,並由接收端進行驗證。
  • 緊急指標:只有當 URG 標誌置 1 時緊急指標才有效。緊急指標是一個正的偏移量,和順序號欄位中的值相加表示緊急資料最後一個位元組的序號。 TCP 的緊急方式是傳送端向另一端傳送緊急資料的一種方式。
  • 選項和填充:最常見的可選欄位是最長報文大小,又稱為MSS(Maximum Segment Size),每個連線方通常都在通訊的第一個報文段(為建立連線而設定SYN標誌為1的那個段)中指明這個選項,它表示本端所能接受的最大報文段的長度。選項長度不一定是32位的整數倍,所以要加填充位,即在這個欄位中加入額外的零,以保證TCP頭是32的整數倍。
  • 資料部分: TCP 報文段中的資料部分是可選的。在一個連線建立和一個連線終止時,雙方交換的報文段僅有 TCP 首部。如果一方沒有資料要傳送,也使用沒有任何資料的首部來確認收到的資料。在處理超時的許多情況中,也會發送不帶任何資料的報文段。

四、UDP頭結構的定義

/*UDP頭定義,共8個位元組*/

typedef struct _UDP_HEADER 
{
 unsigned short m_usSourPort;       // 源埠號16bit
 unsigned short m_usDestPort;       // 目的埠號16bit
 unsigned short m_usLength;        // 資料包長度16bit
 unsigned short m_usCheckSum;      // 校驗和16bit
}__attribute__((packed))UDP_HEADER, *PUDP_HEADER;

 

  • 埠號:用來表示傳送和接受程序。由於 I P層已經把I P資料報分配給T C P或U D P(根據I P首部中協議欄位值),因此T C P埠號由T C P來檢視,而 U D P埠號由UDP來檢視。T C P埠號與UDP埠號是相互獨立的。
  • 長度:UDP長度欄位指的是UDP首部和UDP資料的位元組長度。該欄位的最小值為 8位元組(傳送一份0位元組的UDP資料報是 O K)。
  • 檢驗和:UDP檢驗和是一個端到端的檢驗和。它由傳送端計算,然後由接收端驗證。其目的是為了發現UDP首部和資料在傳送端到接收端之間發生的任何改動。整個UDP報文頭和UDP所帶的資料的校驗和(也包括偽報文頭)。偽報文頭不包括在真正的UDP報文頭中,但是它可以保證UDP資料被正確的主機收到了。因在校驗和中加入了偽頭標,故ICMP除能防止單純資料差錯之外,對IP分組也具有保護作用。

參考資料:

1,https://blog.csdn.net/mrwangwang/article/details/8537775

2,https://blog.csdn.net/hhpingyear/article/details/80216680

3,https://www.cnblogs.com/shenpengyan/p/5912567.html

4,http://blog.51cto.com/lidongfeng/2066272

5,  http://blog.51cto.com/lidongfeng/2066278

6,https://wenku.baidu.com/view/d4043a39bd64783e09122bb3.html

7,https://baike.baidu.com/item/%E5%B8%A7%E6%A0%BC%E5%BC%8F/5921425


有任何問題,請聯絡[email protected]