1. 程式人生 > >網路是怎樣連線的學習筆記-第二章-IP與乙太網的包收發操作(二)

網路是怎樣連線的學習筆記-第二章-IP與乙太網的包收發操作(二)

2.5.3 生成包含接收方 IP 地址的 IP 頭部

IP頭部包含的內容

IP 模組接受 TCP 模組的委託負責包的收發工作,它會生成 IP 頭部並附加在 TCP 頭部前面。

IP 頭部包含的內容如表 2.2 所示,其中最重要的內容就是 IP 地址,它表示這個包應該發到哪裡去。

接受方IP地址:應用程式告知TCP,TCP告知IP模組

這個地址是由 TCP 模組告知的,而 TCP 又是在執行連線操作時從應用程式那裡獲得這個地址的,因此這個地址的最初來源就是應用程式。

IP 不會自行判斷包的目的地,而是將包發往應用程式指定的接收方,即便應用程式指定了錯誤的 IP 地址,IP 模組也只能照做。

當然,這樣做肯定會出錯,但這個責任應該由應用程式來承擔。

在連線操作中傳送第一個 SYN 包時就可能發生這樣的情況,一旦 TCP 連線完畢,就已經確認能夠正常和對方進行包的收發,這時就不會發生這樣的情況了。

傳送方的IP地址來自使用的網絡卡對應的IP地址

IP 頭部的“接收方 IP 地址”填寫通訊物件的 IP 地址。

傳送方 IP 地址需要判斷髮送所使用的網絡卡,並填寫該網絡卡的 IP地址。

如何判斷把包交給哪塊網絡卡

和路由器使用 IP 表判斷下一個路由器位置的操作是一樣的。

因為協議棧的 IP 模組與路由器中負責包收發的部分都是根據 IP 協議規則來進行包收發操作的,所以它們也都用相同的方法來判斷把包傳送給誰。

檢視路由表

這個“IP 表”叫作路由表,我們將在第 3 章探索路由器時詳細介紹它的用法,這裡先簡單講個大概。

如圖 2.18 所示,我們可以通過 route print命令來顯示路由表。

Network Destination 網路目標列

例如TCP 模組告知的目標 IP 地址為 192.168.1.21,那麼就和第 6 行的 192.168.1 的部分相匹配。

Interface 網路介面列

表示網絡卡等網路介面,這些網路介面可以將包傳送給通訊物件。

Gateway 閘道器列

表示下一個路由器的 IP 地址,將包發給這個 IP 地址,該地址對應的路由器就會將包轉發到目標地址。

預設閘道器

路由表的第 1 行中,目標地址和子網掩碼都是 0.0.0.0,這表示預設閘道器,如果其他所有條目都無法匹配,就會自動匹配這一行。 

這樣一來,我們就可以判斷出應該使用哪塊網絡卡來發送包了,然後就可以在 IP 頭部的傳送方 IP 地址中填上這塊網絡卡對應的 IP 地址。

TCP/UDP協議號

接下來還需要填寫協議號,它表示包的內容是來自哪個模組的。

例如,如果是 TCP 模組委託的內容,則設定為 06(十六進位制),如果是 UDP 模組委託的內容,則設定為 17(十六進位制),這些值都是按照規則來設定的。

在現在我們使用的瀏覽器中,HTTP 請求訊息都是通過 TCP 來傳輸的,因此這裡就會填寫表示 TCP 的 06(十六進位制)。

其他欄位內也需要填寫相應的值,但對大局沒什麼影響,我們會在第3 章進行介紹,這裡就先省略了。

註釋

①Gateway(閘道器)在 TCP/IP 的世界裡就是路由器的意思。

②如果 Gateway 和 Interface 列的 IP 地址相同,就表示不需要路由器進行轉發,可以直接將包發給接收方的 IP 地址。我們將在第 3 章詳細介紹。

 

2.5.4 生成乙太網用的 MAC 頭部

MAC頭的作用

生成了 IP 頭部之後,接下來 IP 模組還需要在 IP 頭部的前面加上MAC 頭部(表 2.3)。

IP 頭部中的接收方 IP 地址表示網路包的目的地,通這個地址我們就可以判斷要將包發到哪裡,但在乙太網的世界中,TCP/IP 的這個思路是行不通的。

乙太網在判斷網路包目的地時和 TCP/IP 的方式不同,因此必須採用相匹配的方式才能在乙太網中將包發往目的地,而MAC 頭部就是幹這個用的。

IP 模組在生成 IP 頭部之後,會在它前面再加上 MAC 頭部。

MAC 頭部是乙太網使用的頭部,它包含了接收方和傳送方的 MAC 地址等資訊。

MAC頭的結構

MAC 頭部的開頭是接收方和傳送方的 MAC 地址,和 IP 頭部中的接收方和傳送方 IP 地址的功能差不多,只不過 IP 地址的長度為 32 位元,而 MAC 地址為 48 位元。

IP 地址是類似多少弄多少號這種現實中地址的層次化的結構,而 MAC 地址中的 48 位元可以看作是一個整體。

從表示接收方和傳送方的意義上來說,MAC 地址和 IP 地址是沒有區別的。

以太型別欄位和 IP 頭部中的協議號類似。在 IP 中,協議號表示 IP 頭部後面的包內容的型別,以太型別就表示後面內容的型別。

乙太網包的內容可以是 IP、ARP等協議的包,它們都有對應的值,這也是根據規則來確定的。

以太型別

這裡填寫表示 IP 協議的值 0800(十六進位制)。

傳送方MAC地址

這裡填寫網絡卡本身的 MAC 地址。MAC 地址是在網絡卡生產時寫入 ROM 裡的,只要將這個值讀取出來寫入 MAC 頭部就可以了。

對於多塊網絡卡的情況,類似設定傳送方 IP 地址的方法。

設定傳送方 IP 地址時,我們已經判斷出了從哪塊網絡卡傳送這個包,那麼現在只要將這塊網絡卡對應的 MAC 地址填進去就好了。

注意

實際上,只有在作業系統啟動過程中對網絡卡進行初始化的時候才會讀取MAC 地址,讀取出來之後會存放在記憶體中,每次執行收發操作時實際上使用的是記憶體中的值。

此外,讀取 MAC 地址的操作是由網絡卡驅動程式來完成的,因此網絡卡驅動程式也可以不從網絡卡 ROM 中讀取地址,而是將配置檔案中設定的 MAC 地址拿出來放到記憶體中並用於設定 MAC 頭部,或者也可以通過命令輸入 MAC 地址。

接收方 MAC 地址

只要告訴乙太網對方的 MAC 的地址,乙太網就會幫我們把包傳送過去,那麼很顯然這裡應該填寫對方的 MAC 地址。

此時我們還沒有把包傳送出去,所以先得搞清楚應該把包發給誰,這個只要查一下路由表就知道了。

在路由表中找到相匹配的條目,然後把包發給 Gateway 列中的IP 地址就可以了。

既然已經知道了包應該發給誰,那麼只要將對方的 MAC 地址填上去就好了,但到這裡為止根本沒有出現對方的 MAC 地址,也就是說我們現在根本不知道對方的 MAC 地址是什麼。

因此,我們還需要執行根據 IP 地址查詢 MAC 地址的操作。

 

2.5.5 通過 ARP 查詢目標路由器的 MAC 地址

這裡我們需要使用 ARP ,它其實非常簡單。在乙太網中,有一種叫作廣播的方法,可以把包發給連線在同一乙太網中的所有裝置。

ARP:Address Resolution Protocol,地址解析協議。

ARP 就是利用廣播對所有裝置提問:“×× 這個 IP 地址是誰的?請把你的 MAC 地址告訴我。”

然後就會有人回答:“這個 IP 地址是我的,我的 MAC 地址是××××。”

不是這個 IP 地址的裝置會忽略廣播,什麼都不回答。

如果對方和自己處於同一個子網中,那麼通過上面的操作就可以得到對方的 MAC 地址。

然後,我們將這個 MAC 地址寫入 MAC 頭部,MAC頭部就完成了。

如果路由表的設定正確,那麼對方應該在同一子網,否則對方無法作出ARP 響應,這時只能認為對方不存在,包的傳送操作就會失敗。

ARP快取

不過,如果每次傳送包都要這樣查詢一次,網路中就會增加很多 ARP包,因此我們會將查詢結果放到一塊叫作 ARP 快取的記憶體空間中留著以後用。

在傳送包時,先查詢一下 ARP 快取,如果其中已經儲存了對方的 MAC 地址,就不需要傳送 ARP 查詢,直接使用 ARP 快取中的地址。而當 ARP 快取中不存在對方 MAC 地址時,則傳送 ARP 查詢。

顯示 ARP 快取的方法和 MAC 地址的寫法如圖 2.20 和圖 2.21 所示,供大家參考。

 

 

ARP快取會定時刪除

如果總是使用 ARP快取中儲存的地址會產生問題。

例如當 IP 地址發生變化時,ARP 快取的內容就會和現實發生差異。

為了防止這種問題的發生,ARP 快取中的值在經過一段時間後會被刪除,一般這個時間在幾分鐘左右。

這個刪除的操作非常簡單粗暴,不管 ARP 快取中的內容是否有效,只要經過幾分鐘就全部刪掉,這樣就不會出問題了。

當地址從 ARP 快取中刪除後,只要重新執行一次 ARP 查詢就可以再次獲得地址了。

上面這個策略能夠在幾分鐘後消除快取和現實的差異,但 IP 地址剛剛發生改變的時候,ARP 快取中依然會保留老的地址,這時就會發生通訊的異常。

 

將打包工作交給IP模組的利處

將 MAC 頭部加在 IP 頭部的前面,整個包就完成了。到這裡為止,整個打包的工作是由 IP 模組負責的。

有人認為,MAC 頭部是乙太網需要的內容,並不屬於 IP 的職責範圍,但從現實來看,讓 IP 負責整個打包工作是有利的。

如果在交給網絡卡之前,IP 模組能夠完成整個打包工作,那麼網絡卡只要將打好的包傳送出去就可以了。

對於除 IP 以外的其他型別的包也是一樣,如果在交給網絡卡之前完成打包,那麼對於網絡卡來說,傳送的操作和傳送 IP 包是完全相同的。

這樣一來,同一塊網絡卡就可以支援各種型別的包。

至於接收操作,我們到後面會講,但如果接收的包可以原封不動直接交給 IP 模組來處理,網絡卡就只要負責接收就可以了。

這樣一來,一塊網絡卡也就能支援各種型別的包了。

與其機械地設計模組和裝置之間的分工,導致網絡卡只能支援 IP 包,不如將分工設計得現實一些,讓網絡卡能夠靈活支援各種型別的包。