瀏覽器輸入一個網(wǎng)址發(fā)生了什么(三): IP模塊封裝、ARP協(xié)議、IP協(xié)議、ICMP協(xié)議和網(wǎng)卡原理
上一節(jié)我們探索了網(wǎng)絡消息在協(xié)議棧的TCP模塊內是如何封裝、發(fā)送和接收:瀏覽器輸入一個網(wǎng)址發(fā)生了什么(二) TCP模塊封裝和傳輸機制
本節(jié)將會補充協(xié)議棧中的IP模塊對報文的封裝,以及網(wǎng)絡包是如何通過網(wǎng)卡發(fā)送出去計算機。
1. IP模塊封裝IP頭部
當數(shù)據(jù)報文從TCP模塊傳遞給IP模塊時,IP模塊需要封裝IP頭部。IP頭部中包含以下信息,其中接收方的IP由TCP模塊傳遞給IP模塊,而發(fā)送方的IP是什么需要取決于IP模塊通過電腦的哪一塊網(wǎng)卡發(fā)送(由上一節(jié)我們知道IP不是與主機綁定,而是與主機上的網(wǎng)卡綁定,如果主機上有多個網(wǎng)卡,則該主機可以有多個IP)。
為了得知包由主機上的哪塊網(wǎng)卡發(fā)送,IP模塊會根據(jù)目標IP為條件查詢本機的“路由表”,該路由表在windows系統(tǒng)中可以通過 route print命令顯示,如下:
首先IP模塊會拿目標ip和第1列字段進行比對,這里的比對不是全值匹配,而是只匹配其網(wǎng)絡號。而網(wǎng)絡號的位數(shù)由第2列字段決定。
例如,當目標IP是192.168.1.21時會匹配到倒數(shù)第3行,因為這一行要求比對的網(wǎng)絡號是前24位,而192.168.1.21和192.168.1.0的前24位相同,都是192.168.1。同理,如果目標IP是10.10.1.166則匹配到第3行。
如果目標IP與路由表中的所有條目都不匹配,則會匹配到第1行,第一行的網(wǎng)絡號全為0,即默認網(wǎng)關(網(wǎng)關本質也是一個轉發(fā)路由器),也意味著這個包將被發(fā)送到局域網(wǎng)中默認的一個路由器,由該路由器進行轉發(fā)。
第4列Interface代表網(wǎng)卡的網(wǎng)絡接口,也就是本機網(wǎng)卡的IP。第3列Gateway代表包要被發(fā)送到的下一個路由器的IP。
如果目標IP是192.168.1.21,則會匹配到倒數(shù)第3行,此時IP模塊會用第4列的10.10.1.16代表的網(wǎng)卡發(fā)送包到第3列的10.10.1.2這個路由器。
從上面的路由表來看,該主機只有10.10.1.16這1個IP,1塊網(wǎng)卡。
第5列表示從發(fā)送方IP到目標IP需要經歷多少跳,即包傳輸?shù)木嚯x。
回到正題,除了發(fā)送方IP和目標IP,IP頭部還需要填寫協(xié)議號,它表示包的內容是來自哪個模塊的。例如,如果是TCP模塊委托的內容,則設置為06(十六進制),如果是UDP模塊委托的內容,則設置為 17(十六進制),這些值都是按照規(guī)則來設置的。
在現(xiàn)在我們使用的瀏覽器中, HTTP請求消息都是通過TCP來傳輸?shù)?,因此這里就會填寫表示TCP的06(十六進制)。其他字段內也需要填寫相應的值,但對大局沒什么影響,這里先省略。
2. IP模塊封裝以太網(wǎng)用的MAC頭部
IP頭部中的IP地址可以由網(wǎng)絡層的IP模塊進行識別(當包到達接收方的IP模塊后,在IP模塊中會檢查包頭部的目標IP地址是否為接收方的IP地址,如果不是則丟棄包;除了IP地址外,IP模塊還會識別IP頭部中的其他信息如協(xié)議號等)。
但是在以太網(wǎng)(以太網(wǎng)是局域網(wǎng)中的一種)中,有很多設備只有數(shù)據(jù)鏈路層而沒有網(wǎng)絡層,沒有IP模塊,因此也無法識別IP頭部,例如集線器等。此時需要為包添加以太網(wǎng)能識別的MAC頭部,如下所示:
MAC頭部實際上也是IP模塊生成的,它包含了接收方和發(fā)送方的MAC地址,此時包從IP包變成以太網(wǎng)包。以太網(wǎng)包的內容不一定是IP包,也可以是ARP包等,可以從MAC頭部的以太網(wǎng)類型字段得知。
MAC地址也是網(wǎng)卡的硬件地址。IP和MAC都是網(wǎng)卡的地址,但IP地址是可以動態(tài)變化的,這取決于主機所處的網(wǎng)絡環(huán)境,而MAC地址是固定的,當網(wǎng)卡生產時就寫入到ROM中,在上一步中根據(jù)目標IP查詢路由表得知該由哪塊網(wǎng)卡發(fā)送包后,再從這塊網(wǎng)卡中讀取MAC地址并寫入MAC頭部即可。
下面是MAC地址的格式:
得知發(fā)送方的MAC地址容易,那如何得知接收方的MAC地址呢?這里需要使用ARP協(xié)議和廣播。
ARP協(xié)議(地址解析協(xié)議)是一個實現(xiàn)從IP地址到MAC地址的映射,即詢問目標IP其 對應的MAC地址的協(xié)議。ARP協(xié)議僅用于IPv4,IPv6則是使用NDP(鄰居發(fā)現(xiàn)協(xié)議)。
ARP協(xié)議與IP協(xié)議處于同一層,也是網(wǎng)絡層協(xié)議,因此ARP報文是在網(wǎng)絡層被封裝的網(wǎng)絡包。
ARP的工作機制:
- 首先IP模塊會封裝ARP請求包,ARP請求包中包括發(fā)送方的IP地址和MAC地址,以及目標主機的IP地址(這段話中的目標主機的IP地址其實是下一跳路由器的IP地址而非最終互聯(lián)網(wǎng)另一端的目標IP)和MAC地址(由于不知道目標主機的MAC地址,因此會填寫為全0)。
- 客戶端計算機通過交換機向局域網(wǎng)內同一鏈路的所有機器發(fā)送ARP請求(即廣播),該ARP請求包在數(shù)據(jù)鏈路層會被同一鏈路上所有的主機、路由器和交換機接收和解析。
- 交換機接收到這個ARP請求包(應該說是包含該ARP包的幀)會將其廣播到同一鏈路的其他機器(因為交換機只負責數(shù)據(jù)的轉發(fā),它沒有網(wǎng)絡層且它沒有被分配IP);
- 之后這個包被路由器或主機接收到,則他們會檢測ARP包頭部的目標IP地址,如果不是自己的IP地址則會丟棄該包。如果是則會將他們自己的MAC地址寫入到ARP響應包返回給發(fā)送方主機。并且目標主機會將發(fā)送方主機的IP地址和MAC地址的映射關系緩存到ARP表中。
ARP表是每個主機內存儲著其他機器的IP和MAC地址的映射關系表。通過查詢ARP緩存就不用每次查詢MAC地址時都去進行ARP請求廣播,從而防止ARP大量廣播。但是ARP表中的每條緩存都有自己的有效期,過期則刪除,有效期在幾分鐘到十幾分鐘??梢酝ㄟ^ arp -a命令查看ARP表內容。
回到正題,將目標主機的MAC地址寫入到MAC頭部之后,MAC包就封裝好了,接下來IP模塊會將MAC包傳遞給網(wǎng)卡,網(wǎng)卡對MAC包進一步封裝為幀(無論是IP包還是ARP包,都會在網(wǎng)卡被封裝為幀之后才發(fā)送出去)。
需要注意的是,此時網(wǎng)絡包MAC頭部的接收方MAC地址是下一跳路由器的MAC地址而非互聯(lián)網(wǎng)另一端目標主機的MAC地址。當然如果這個包的目標主機本身就是局域網(wǎng)中的一臺機器,那么發(fā)送ARP請求時的ARP頭部的目標IP就可能是目標主機的IP而非路由器IP,那么請求的MAC地址就直接是這個目標主機的MAC地址。
3. 網(wǎng)絡包封裝成幀
在介紹數(shù)據(jù)包封裝成幀并發(fā)送之前先介紹一下網(wǎng)卡和數(shù)據(jù)在網(wǎng)卡傳輸?shù)穆窂健?/p>
網(wǎng)卡和網(wǎng)卡驅動程序
IP模塊生成的網(wǎng)絡包是存在內存中的一堆數(shù)字信息,需要被轉為電或光信號才能在網(wǎng)線傳輸,而網(wǎng)卡負責這一任務。網(wǎng)卡本身是硬件,無法完成這些任務,還需要網(wǎng)卡驅動程序對網(wǎng)卡進行操作和控制。
網(wǎng)卡在電腦開機時會進行初始化,初始化時網(wǎng)卡驅動程序會讀取ROM中的MAC地址并分配給網(wǎng)卡中的MAC模塊,此時網(wǎng)卡的MAC地址才生效。
下圖是網(wǎng)卡的結構以及網(wǎng)絡包是如何在網(wǎng)卡中處理和發(fā)送的:
其中,MAC模塊負責將IP包封裝為幀,并檢測接收到其他機器發(fā)送過來的幀是否正確(FCS校驗)以及接收到的包中的目標MAC地址是否是自己的MAC地址;PHY(MUA)負責將幀從數(shù)字信息轉為能在網(wǎng)線傳輸?shù)碾娦盘枴?/p>
IP模塊將以太網(wǎng)包傳遞給網(wǎng)卡驅動,網(wǎng)卡驅動會將其復制到網(wǎng)卡內的緩沖區(qū),再向MAC模塊發(fā)送發(fā)送包的命令。MAC模塊將包從緩沖區(qū)取出在開頭加上報頭和起始幀分界符,在末尾加上用于檢測錯誤的幀校驗序列,此時網(wǎng)絡包被封裝成幀。
報頭是一串像10101010…這樣1和0交替出現(xiàn)的比特序列,長度為56比特,它的作用是確定包的讀取時機。起始幀分界符是一個用來表示包起始位置的標記。末尾的FCS(幀校驗序列)用來檢查包傳輸過程中因噪聲導致的波形紊亂、數(shù)據(jù)錯誤。
4. 向集線器發(fā)送網(wǎng)絡包
包封裝成幀后,MAC模塊從報頭開始將數(shù)字信息按每個比特轉換成電信號,然后由PHY,或者叫MAU的信號收發(fā)模塊發(fā)送出去。在網(wǎng)線中實際的輸出信號如下
發(fā)送信號的操作分為兩種,一種是使用集線器的半雙工模式,另一種是使用交換機的全雙工模式。
在使用集線器的半雙工模式中,發(fā)送和接收不能同時進行,PHY(MAU)模塊會保證網(wǎng)線中沒有其他設備發(fā)送信號給自己才會將自己的信號發(fā)送出去(如果有則等待其他信號傳輸完)。如果網(wǎng)線中有其他信號在傳輸?shù)那闆r下發(fā)送出去自己的信號,則兩組信號會發(fā)生碰撞。在全雙工模式中,發(fā)送和接收能夠同時進行。
電信號由PHY(MUA)信號收發(fā)模塊發(fā)送給自己連接的集線器,再由集線器轉發(fā)給連接到該集線器上的所有設備。數(shù)據(jù)在網(wǎng)絡中(局域網(wǎng)中)傳遞的過程如下:
信號經集線器發(fā)給所有設備后,這些設備都會接收到這個信號,然后由他們的PHY(MUA)模塊從電信號轉為通用格式給MAC模塊。
MAC模塊先將信號轉為數(shù)字信息(還原為數(shù)據(jù)幀),然后檢測數(shù)據(jù)幀是否受到噪聲干擾而紊亂,即把包開頭到結尾的比特套用公式計算出的內容與幀末尾的FCS比對,如果不一致則會被當做錯誤包丟棄。
如果FCS校驗沒問題,MAC模塊會檢測包MAC頭部的接收方MAC地址是否是自己的MAC地址,不是則直接丟棄,是則存到網(wǎng)卡緩沖區(qū)中。
之后網(wǎng)卡會發(fā)出中斷信號給CPU。換句話說,計算機不會一直監(jiān)控網(wǎng)卡的活動而是在運行其他的任務,因此操作系統(tǒng)是無法得知包到達網(wǎng)卡這件事。
因此包到達后需要由網(wǎng)卡向擴展總線中的中斷信號線發(fā)送信號,該信號線通過中斷控制器連接到CPU,CPU接收到中斷信號后會掛起正在處理的任務,切換到操作系統(tǒng)的中斷處理程序,中斷處理程序會調用網(wǎng)卡驅動,網(wǎng)卡驅動從網(wǎng)卡緩沖區(qū)取出包交給TCP/IP協(xié)議棧。
協(xié)議棧中,IP模塊會校驗IP頭部格式是否正確,以及包的頭部接收方IP地址是否是自己的地址,如果不是自己的地址,IP模塊會通過ICMP消息將錯誤告知發(fā)送方,但不會將這個包轉發(fā)給真正的目標IP主機。
接下來需要再說一下 ICMP 互聯(lián)網(wǎng)控制協(xié)議。
該協(xié)議用于在主機和路由器之間發(fā)送控制消息,這里的控制消息是指“網(wǎng)絡不通”,“主機是否可到達”等消息,這些消息不傳輸用戶數(shù)據(jù)。ICMP位于網(wǎng)絡層,但是在IP之上,ICMP報文和TCP與UDP一樣會被添加IP頭部封裝為包。ICMP是無連接的協(xié)議。
ICMP的主要功能有兩個:
- 確認IP包是否成功到達目標地址,當IP包從源發(fā)送方到目標主機之間的任何一個設備(如路由器)出錯(如包無法到達下一跳的設備),則中間的設備會生成ICMP數(shù)據(jù)包發(fā)送給源發(fā)送方。
- 網(wǎng)絡診斷,ICMP可以檢測兩臺設備之間能否互連,即主機A能否到達主機B,以及主機A與主機B的連接速度,準確報告ICMP包到達目標地的時間。ping和traceroute命令就是通過發(fā)送ICMP包實現(xiàn)的功能。其中traceroute可以顯示兩臺機器之間可能的路徑并測量數(shù)據(jù)包在IP網(wǎng)絡上的時延,ping則是traceroute的簡化版,功能與traceroute類似。
IP包不可到達目標主機情況下發(fā)送ICMP包的流程:
圖中,主機A發(fā)送了一個IP數(shù)據(jù)包,其目標地址是主機B。IP包經過路由器1到達路由器2,假設路由器2和主機B在同一鏈路,為了根據(jù)主機B的IP獲取B的MAC地址,路由器2在局域網(wǎng)內廣播了ARP包。由于主機B關機導致該ARP包沒有被響應,多次重發(fā)ARP無果后,路由器2會生成一個類型為“目標不可到達類型”的ICMP包經過路由器1發(fā)送主機A。
“目標不可到達”是其中的一種ICMP消息類型。
主要的ICMP的消息類型如下:
通知類型(十進制數(shù)) | 具體內容 |
0 | 回送應答(Echo Reply) |
3 | 目標不可達(Destination Unreachable) |
4 | 原點抑制(Source Quench) |
5 | 重定向或改變路由(Redirect) |
8 | 回送請求(Echo Request) |
9 | 路由器公告(Router Advertisement) |
10 | 路由器請求(Router Solicitation) |
11 | ICMP 超時(Time Exceeded) |
17 | 地址子網(wǎng)請求(Address Mask Request) |
18 | 地址子網(wǎng)應答(Address Mask Reply) |
ICMP通知類型分為兩類:對于發(fā)送錯誤消息的ICMP報文叫差錯報文;對于為了采集信息和配置的ICMP報文叫信息類報文(如ping和traceroute命令所發(fā)的ICMP報文)。
ping命令檢測兩端主機能否互連情況下發(fā)送ICMP包的流程:
圖中主機A執(zhí)行ping命令檢測能否與主機B通信,此時主機A會生成一個通知類型為“8 回送請求”的ICMP包給B。ICMP包經過多個路由器如果能夠到達主機B則B接收到“回送請求”的ICMP包后會返回一個“0 回送應答”的ICMP包給A,這個包會沿著原路經過路由器4~1到達主機A,主機A就知道能夠與B通信,以及包送達B花費的時間。
回到正題,當接收方主機發(fā)現(xiàn)數(shù)據(jù)包頭部的接收方IP地址不是自己的IP地址,則會由IP模塊生成一個類型為 “目標不可到達類型”的ICMP包給源發(fā)送方。
如果IP正確,則這個包會被接收。如果這個包是經過分片的,則IP模塊會將其暫存到內存中,等IP頭部具有相同ID號的包全部到達,會根據(jù)ID號以及IP頭部的“分片偏移量”將所有分片重組完整的IP包。(這里的分片不是指TCP模塊對應用程序數(shù)據(jù)[即http消息]的拆分,而是指路由器對某個以太網(wǎng)包內部IP包數(shù)據(jù)[即TCP頭部+http消息]的拆分,這部分知識會在之后介紹路由器時介紹)。
之后,這個完整IP包的數(shù)據(jù)會被遞交給TCP模塊,TCP模塊根據(jù)IP頭部的接收方IP地址和TCP頭部的接收方端口號查找對應的套接字,根據(jù)套接字記錄的通信狀態(tài)執(zhí)行相應操作:如果包的數(shù)據(jù)是應用程序數(shù)據(jù)則返回確認接收的ACK包,并將數(shù)據(jù)存放到緩沖區(qū)等待應用程序來讀??;如果是建立或斷開連接的控制包,則返回響應控制包,并告知應用程序建立和斷開連接的操作狀態(tài)。
說到這里,我們可以說已經大概了解了發(fā)送方數(shù)據(jù)從本機的應用層到本機網(wǎng)絡層的傳輸和處理,以及接收方接收數(shù)據(jù)時數(shù)據(jù)從接收方機器的網(wǎng)絡層到應用層的傳輸與處理過程了。
下節(jié)預告:瀏覽器輸入一個網(wǎng)址發(fā)生了什么(四) 網(wǎng)絡包在局域網(wǎng)中的傳輸