1. 程式人生 > >乙太網幀、IP 幀、UDP/TCP幀、http 報文結構解析

乙太網幀、IP 幀、UDP/TCP幀、http 報文結構解析

我們從 OSI/RM 參考模型入手,來看 OSI/RM 七層模型中的每一層資料幀結構。

一 OSI/RM 結構

OSI 是不同製造商的裝置和應用軟體在網路中進行通訊的標準,此模型已經成為計算機間和網路間進行通訊的主要結構模型, 目前使用的大多數網路通訊協議的結構都是基於 OSI 模型的。OSI 包括體系結構、服務定義和協議規範三級抽象。OSI 體系結構定義了一個七層模型用於進行程序間的通訊,並作為一個概念性框架來協調各層標準的制定;OSI 的服務定義描述了各層所提供的服務,以及層與層之間的抽象介面和互動用的服務原語;OSI 各層的協議規範精確的定義了應當傳送何種控制資訊及何種過程來解釋該控制資訊。OSI/RM 七層結構以及各層的基本功能如下。

1. 物理層:物理層是 OSI 參考模型的最低層,它的任務是為它的上一層(資料鏈路層)提供一個物理連線,以便透明地傳送位元流,即經過實際電路傳送後的位元流沒有發生變化,物理層好像是透明的,對其中的傳送內容不會有任何影響,任意的位元流都可以在這個電路上傳送。

2. 資料鏈路層:鏈路是指兩個相鄰節點間的傳輸線路,是物理連線,資料鏈路表示傳輸資料的鏈路,是邏輯連線。資料鏈路層把物理層提供的可能出錯的鏈路(物理連線)改造成為邏輯上無差錯的資料鏈路,使之對網路層表現為一條無差錯的鏈路。資料鏈路層將傳送的資料組織成的資料鏈路協議資料單元稱為資料幀。在 OSI 參考模型中,資料鏈路層位於第二層,區域網的標準將資料鏈路層分為兩個子層:邏輯鏈路控制子層(LLC)與介質訪問控制子層(MAC)。資料鏈路層的主要功能是將網路層接收到的資料分割成特定的可被物理層傳輸的幀。

3. 網路層:網路層是 OSI 參考模型中的第三層,它傳送的資料單元是資料“分組”。它的任務是在資料鏈路層提供的兩個相鄰節點之間的資料幀的傳送基礎上,選擇合適的路由與交換節點,使從源節點傳輸層得到的資料能準確無誤、高效地到達目的節點,並交付給目的節點的傳輸層,主要功能是路由選擇、阻塞控制、網路互聯。網路層提供了虛電路服務(網路層向傳輸層提供的一種使所有分組按順序到達目的端系統的可靠的資料傳送方式,是一種面向連線的服務)和資料報服務(資料報服務一般僅由資料報交換網來提供,端系統的網路層同網路節點的網路層之間均按照資料報方式交換資料,是一種面向無連線的服務)。

4. 傳輸層:在 OSI 參考模型中的第四層,第一、二、三層是面向通訊的通常稱為通訊子網,第五、六、七層面嚮應用的通常稱為資源子網,負責端到端的可靠傳輸,實現資料通訊中通訊子網向資源子網的過渡,傳輸層傳輸資訊的單位稱為報文,負責總體資料的傳輸和控制。這一層主要定義了兩個傳輸協議,TCP 以及 UDP 協議。

5. 會話層:在 OSI 參考模型的第五層,負責在網路中的兩個節點之間建立和維持通訊。會話層的功能包括:建立通訊連結和保持會話過程通訊連結的暢通,同步兩個節點之間的對話,決定通訊是否被中斷以及通訊中斷時決定從何處重新發送。

6. 表示層:在 OSI 參考模型的第六層,表示層中資料將按照網路能理解的方案進行格式轉化,管理資料的解密與加密,還對圖片和檔案格式資訊進行解碼和編碼。表示層提供兩類服務:相互通訊的應用程序間交換資訊的表示方法與表示連線服務。

7. 應用層:在 OSI 參考模型的最高層:負責對軟體提供介面以使程式能享用網路服務。應用層提供的服務包括檔案傳輸、檔案管理以及電子郵件的資訊處理。

二 TCP | IP 協議

Internet 協議集是對 ISO/OSI 的簡化,其主要功能集中在 OSI 的第三、四層,通過增加軟體模組來保證和已有系統的最大相容性。現在 TCP | IP 協議集已成為 Internet 的標準,應用最為廣泛,TCP | IP 協議集包括多種協議,如下圖所示:

三 乙太網幀 

在資料鏈路層中,使用最多的就是乙太網,而乙太網幀因為歷史原因存在多個版本,這裡採用 IEEE 802.3 以太幀格式。

前導碼:7 個位元組,用於資料傳輸過程中的雙方傳送與接收的速率的同步。

SFD:幀開始符,1 個位元組,用於標識一個乙太網幀的開始。 

目的 MAC 地址:6 個位元組,指明幀的接收者。

源 MAC 地址:6 個位元組,指明幀的傳送者。

長度:2 個位元組,指明該幀資料欄位的長度,但不代表資料欄位長度能夠達到 2^16 位元組。

型別:2 個位元組,指明幀中資料的協議型別,比如常見的 IPv4 中的 ip 協議採用 0x0800。

資料與填充:46~1500 個位元組,包含了上層協議傳遞下來的資料,如果加入資料欄位後幀長度不夠 64 位元組,會在資料欄位加入填充欄位達到 64 位元組。

校驗和:4 個位元組,對接收網絡卡(主要是檢測資料與填充欄位)提供判斷是否傳輸錯誤的一種方法,如果發現錯誤,則丟棄此幀。目前最為流行的用於校驗和(FCS)的演算法是迴圈冗餘校驗(cyclic redundancy check -- CRC)。

四 IP幀

IP 協議是 TCP/IP 協議族中最為核心的協議,它提供不可靠的、無連線的服務,也即依賴其他層的協議進行差錯控制。在區域網中,IP 協議往往被封裝在乙太網幀中傳送,而所有的 TCP、UDP、ICMP、IGMP 資料都被封裝在 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;

版本:4 位,用來表明 IP 協議實現的版本號,當前一般為 IPv4,即 0100,IPv6 的為 0110,這個欄位確保可能執行不同 IP 版本的裝置之間的相容性。

首部長度:即報頭長度,4 位,以 32 bit 的字來定義 IP 首部的長度,包括可選項。若該欄位的最小值是 5 (標準頭部長度),即 5*32=160 位元 =20 位元組,此欄位最大值為15 (有擴充套件部分),即15*32 =480 位元 = 60 位元組。

服務型別:8位,用於攜帶提供服務質量特徵資訊的欄位,服務型別欄位聲明瞭資料報被網路系統傳輸時可以被怎樣處理。其中前 3 位元位優先權子欄位(Precedence,現已被忽略,各種終端都不採用)。第 8 位元保留未用。第 4 至第 7 位元分別代表延遲、吞吐量、可靠性和花費,當它們取值為 1 時分別代表要求最小時延、最大吞吐量、最高可靠性和最小花費,這 4 位元的服務型別中只能置其中 1 位元為 1,可以全為 0 ,若全為 0 則表示一般服務,大多數情況下該服務型別會被忽略。

總長度:16 位,指明整個資料報的長度,按位元組計算,最大長度為 2^16 位元組。

標識:16 位,用來唯一標識主機發送的每一份資料報,IP 軟體會在儲存器中維持一個計數器,每產生一個數據段,計數器就加 1,並將此值賦給標誌欄位。但這個“標識”並不是序號,因為 IP 是無連線服務,資料報不存在按序接收問題,如資料報由於超過網路的 MTU (最大傳送單元) 而必須分片時,這個標誌欄位的值就會被複制到所有的資料報的標識欄位中,相同的標識欄位的值使分片後各資料報片能正確的重灌成為原來的資料報。

標誌:3 位,分別是 RF、DF、 MF,目前只有 DF,MF 有效,DF(don't fragment),置為 0 時表示可以分段,置為 1 時是不能被分段,MF(more fragment),置為 0 時表示該資料段為最後一個數據段,置為 1 時表示後面還有被分割分段。

段偏移量:13 位,指出較長的分組在分段後,某段在原分組的相對位置。也就是說相對使用者欄位的起點,該片從何處開始。段偏移以 8 個位元組(有 3 位被 flags 佔據)為偏移單位,這就是每個分片的長度一定是 8 位元組 (64位) 的整數倍。

生存期:8 位,用來設定資料報最多可以經過的路由器數,由傳送資料的源主機設定,通常為 32、64、128等,每經過一個路由器,其值減 1 ,直到 0 該資料報被丟棄。

協議:8 位,指明 ip 資料欄位中的資料採用上層什麼協議封裝的,常見的有 ICMP(1)、IGMP(2)、TCP(6)、UDP(17)

首部校驗和:16位,填充根據 ip 頭部計算得到的校驗和碼。計算方法是:對頭部中每個 16 位元進行二進位制反碼求和,但不含涉及頭部後的資料欄位。

源 IP 地址:源 ip 地址,32 位。

目的 IP 地址:目標 ip 地址,32 位。

選項:n*32 位,用來定義一些可選項:如記錄路徑、時間戳等,但這些選項很少被使用,同時並不是所有主機和路由器都支援這些選項。可選欄位的長度必須是 32 位元的整數倍,如果不足,必須填充 0 以達到此長度要求,根據 IHL(首部長度) 可以得到選項的長度。

資料:不定長度,但受限於資料報的最大長度 2^16 ,這是在資料報中要傳輸的資料,它是一個完整的較高層報文或報文的一個分片。

五 UDP 幀

UDP(User Datagram Protocol) 即使用者資料報協議,在網路中它與 TCP 協議一樣用於處理資料包,是一種不可靠(服務不用確認、不對報文排序、不進行流量控制,可能會出現丟失、重複、失序現象)、無連線(在主機間不建立會話)的協議,在 OSI 模型中的第四層--傳輸層,處於 IP 協議的上一層。由於 UDP 傳輸不是可靠性服務,所以幀結構較為簡單,而且處理與傳送速率高,開銷要求低,支援點對點和一點對多點的通訊,經常用作音訊、視訊和普通資料的傳輸協議,因為它們即使偶爾丟失一兩個資料包,也不會對接收結果產生太大影響。

/*UDP 頭定義,共 8 個位元組*/
typedef struct_UDP_HEADER
{
    unsigned short m_usSourPort;     //源埠號 16 bit
    unsigned short m_usDestPort;     //目的埠號 16 bit
    unsigned short m_usLength;      //資料包長度 16 bit
    unsigned short m_usCheckSum;    //校驗和 16 bit
}__attribute__((packed))UDP_HEADER,*PUDP_HEADER;

源埠:16 bit (2 個位元組),是一個大於 1023 的 16 位數字,由基於 UDP 應用程式的使用者程序隨機選擇。

目的埠:16 bit (2 個位元組),指明接收者所用的埠號,一般由應用程式來指定。

資料長度:16 bit (2 個位元組),標明 UDP 頭部和 UDP 資料的總位元組長度。

校驗和欄位:16 bit (2 個位元組),用來對 UDP 頭部和 UDP 資料進行校驗。與 TCP 不同的是,此欄位是可選項,而 TCP 資料段中必須包含校驗和欄位。

資料:不定長度,為上層協議封裝好的資料。

六 TCP 幀

TCP(Transmission Control Protocol) 即傳輸控制協議,是一種面向連線的(需通過三次握手來建立 TCP 連線,在主機間建立會話)、可靠的(TCP 通過確認和按順序傳遞來確保資料的傳遞)、基於位元組流的傳輸層通訊協議,但 TCP 傳輸比較慢,開銷略高,並且只支援點對點通訊。當應用層向 TCP 層傳送用於網間傳輸的 8 位元組表示的資料流,TCP 則把資料流分割成適當長度的報文段,最大傳輸段大小(MSS)通常受該計算機連線的網路的資料鏈路層的最大傳送單元(MTU)限制,之後 TCP 把資料包傳給 IP 層,由它來通過網路將包傳送給接收端實體的 TCP 層。

/*TCP 頭定義,共 20 個位元組*/
typedef struct_TCP_HEADER
{
    short m_sSourPort;                  //源埠號 16 bit
    short m_sDestPort;                  //目的埠號 16 bit
    unsigned int m_uiSeqNum;            //序列號 32 bit
    unsigned int m_uiAcknowledgeNum;    //確認號 32 bit
    short m_sHeaderLenAndFlag;          //前4位:TCP 頭長度;中6位:保留;後6位:標誌位
    short m_sWindowSize;                //視窗大小 16 bit
    short m_sCheckSum;                  //校驗和 16 bit
    short m_surgentPointer;             //緊急資料偏移量 16 bit
}__attribute__((packed))TCP_HEADER,*PTCP_HEADER;

 源埠:2 個位元組,是一個大於 1023 的 16 位數字,由基於 TCP 應用程式的使用者程序隨機選擇。

目的埠:2 個位元組,指明接收者所用的埠號,一般由應用程式來指定。

順序號:4 個位元組,用來標識從 TCP 源端向 TCP 目的端傳送的資料位元組流,它表示在這個報文段中的第一個資料位元組的順序號。如果將位元組流看作在兩個應用程式間的單向流動,則 TCP 用順序號對每個位元組進行計數,序號是 32 bit 的無符號數,序號達到 2^32-1 後又從 0 開始。比如我們收到一個數據報中 sq(順序號) =0,資料報內容為 20 位元組,那麼下一個資料報的 sq 就應該是 21。當建立一個新的連線時,SYN 標誌變為 1,順序號欄位包含由這個主機選擇的該連線的初始順序號 ISN。

確認序號:4 個位元組,包含傳送確認的一端所期待收到的下一個順序號。因此,確認序號應該是上次已經成功收到資料位元組順序號加 1 。比如我們收到的一個數據報的 sq = 0 ,資料報內容為 20 位元組,那麼我們的 ack(確認序號) 應該是 21 ,用來表明 sq=0 ,內容為 20 位元組的資料報已經收到,接下來期望收到的是 sq=21 的資料報。只有 ACK 標誌為 1 時確認序號欄位才有效。

報文長度:4 位,給出報頭中 32 bit 字的數目,需要這個值是因為任選欄位的長度是可變的,這個欄位佔 4 bit,即 TCP 最多有 60 (15*4) 位元組的首部。

保留區:6 位,保留給將來使用,目前必須置為 0 。

控制位:6位,控制位包括

URG:為 1 表示緊急指標有效,為 0 則忽略緊急指標值。

ACK:為 1 表示確認號有效,為 0 表示報文中不包含確認資訊,忽略確認號欄位。

PSH:為 1 表示是帶有 PUSH 標誌的資料,表示傳送端快取中已經沒有待發送的資料,指示接收方應該儘快將這個報文段交給應用層而不用等待緩衝區裝滿。

RST:用於復位由於主機崩潰或其他原因而出現錯誤的連線。它還可以用於拒絕非法的報文段和拒絕連線請求。一般情況下,如果收到一個 RST 為 1 的報文,那麼一定發生了某些問題。

SYN:同步序號,為 1 表示連線請求,用於建立連線和使順序號同步。

FIN:用於釋放連線,為 1 表示傳送方已經沒有資料傳送了,即關閉本方資料流。

視窗大小:2 個位元組,表示從確認號開始,本報文的源方可以接收的位元組數,即源方接收視窗的大小。視窗大小是一個 16 bit 欄位,因而視窗大小最大為  2^16-1 。

校驗和:2 個位元組,對整個的 TCP 報文段(包括 TCP 頭部和 TCP 資料以及偽報文頭)進行校驗和計算。這是一個強制性的欄位,要求由傳送方計算和儲存,並由接收端進行驗證(接收端要與傳送端數值結果完全一樣,才能證明資料是有效的)。

緊急指標:2 個位元組,是一個正的偏移量,和順序號欄位中的值相加表示緊急資料最後一個位元組的序號。TCP 的緊急方式是傳送端向另一端傳送緊急資料的一種方式,只有當 URG 標誌置為 1 時緊急指標才有效。

選項:n*4 位元組,常見的可選欄位是最長報文大小 MSS(Maximum Segment Size)。每個連線方通常都在通訊的第一個報文段 (為建立連線而設定 SYN 標誌的那個段) 中指明這個選項,它指明本端所能接收的最大長度的報文段。選項長度不一定是 32 位字的整數倍,所以需要新增填充位,使得報文長度為 32 位字的整數倍。

資料:不定長度,為上層協議封裝好的資料。

七 HTTP 報文

HTTP 是建立在 TCP | IP 上層的應用層協議,,可以保證客戶端(特別是Web瀏覽器)正確和快速地傳輸超文字檔案資訊,而且是一個基於 請求/響應 模式的無狀態協議,自由度更高,是面向文字的,報文中的每一個欄位都是一些 ASCALL 碼串,各個欄位的長度是不確定的。報文型別可以分為兩種:請求報文和響應報文(都是由一個請求起始行、一個或多個頭域、一個標識頭域結束的空行和可選的訊息體組成)。

請求報文

 1. 請求行:

請求行包括請求方法、URL、協議版本,它們之間用空格分隔(所以我們輸入的 URL 是不允許帶有空格),且都不定長度。

請求方法:常用的 POST (將表單資料存入請求體裡面,多數用於上傳資料),GET(將請求引數都放置在 URL+? 後,引數之間用 & 連線,用於獲取資料),HEAD (服務端只返回響應頭,所以處理響應速度快,用於檢測請求是否可用)。

2. 請求頭

每一行以鍵值對的形式寫入,鍵值間用 :分割,多個值之間以 ;分割,每行以回車符換行符結束。常見的鍵有:User-Agent:產生請求的瀏覽器型別;Accept:客戶端可識別的內容型別列表;Host:請求的主機名,允許多個域名同處一個 IP 地址;Range:指定請求實體的一個或者多個子範圍,採用多執行緒下載時可以設定該鍵。要注意請求頭與請求體間有一個空行,它表示通知服務端沒有更多請求頭了,下面的都是請求體。

3. 請求體

請求資料不在 GET 方法中使用,而是在 POST 方法中使用,POST 方法適用於需要客戶填寫表單的場合。

響應報文 

1. 狀態行:

狀態行包括協議版本,狀態碼,狀態碼描述,常見的一個狀態行的例子是(HTTP/1.1 200 OK),其中 200 表示請求正常狀態碼中的第一個數字定義了相應的類別,第一個數字可以取如下所示的 5 個不同的值之一,含義如下。

1XX:資訊響應類,表示接收到請求並且繼續處理。

2XX:請求處理成功的響應類,表示請求被成功接收和處理,如 HTTP 200 (表示一切正常)。

3XX:重定向響應類,為了完成指定的請求動作,必須接受進一步的請求處理。

4XX:客戶端錯誤,客戶請求包含語法錯誤或者不能正確執行,如 HTTP 400 (表示請求無效)。

5XX:服務端錯誤,伺服器不能正常執行一個正確的 HTTP 請求,如 HTTP 500 (伺服器內部出現錯誤)。

2. 響應頭:

與請求頭類似,通過鍵值對的形式向客戶端傳遞關鍵訊息,常見的有:Content-Type:用於向接收方指示實體的介質型別;Content-Range:用於向接收方指示實體的傳送範圍;Content-Length:用於向接收方指示實體的傳送長度;Date:傳送系統的日期與時間。

3. 響應體:

服務端真正返回的文字資料,如果客戶端請求一個網頁的話,該資料段將填充請求的 html 文字。