圖解 | 原來這就是網絡

 

你是一臺電腦,你的名字叫 A算法

 

好久好久以前,你不與任何其餘電腦相鏈接,孤苦伶仃。編程

直到有一天,你但願與另外一臺電腦 B 創建通訊,因而大家各開了一個網口,用一根網線鏈接了起來。緩存

 

用一根網線鏈接起來怎麼就能"通訊"了呢?我能夠給你講 IO、講中斷、講緩衝區,但這不是研究網絡時該關心的問題。安全

若是你糾結,要麼去研究一下操做系統是如何處理網絡 IO 的,要麼去研究一下包是如何被網卡轉換成電信號發送出去的,要麼就僅僅把它當作電腦裏有個小人在開槍吧~網絡

反正,大家就是連起來了,而且能夠通訊。數據結構

 

第一層

 

有一天,一個新夥伴 C 加入了,但聰明的大家很快發現,能夠每一個人開兩個網口,用一共三根網線,彼此相連。併發

隨着愈來愈多的人加入,你發現身上開的網口實在太多了,並且網線密密麻麻,混亂不堪。(而實際上一臺電腦根本開不了這麼多網口,因此這種連線只在理論上可行,因此連不上的我就用紅色虛線表示了,就是這麼嚴謹哈哈~)佈局

因而大家發明了一箇中間設備,大家將網線都插到這個設備上,由這個設備作轉發,就能夠彼此之間通訊了,本質上和原來同樣,只不過網口的數量和網線的數量減小了,再也不那麼混亂。學習

你給它取名叫集線器,它僅僅是無腦將電信號轉發到全部出口(廣播),不作任何處理,你以爲它是沒有智商的,所以把人家定性在了物理層動畫

 

因爲轉發到了全部出口,那 BCDE 四臺機器怎麼知道數據包是否是發給本身的呢?

首先,你要給全部的鏈接到交換機的設備,都起個名字。原來大家叫 ABCD,但如今須要一個更專業的,全局惟一的名字做爲標識,你把這個更高端的名字稱爲 MAC 地址

你的 MAC 地址是 aa-aa-aa-aa-aa-aa,你的夥伴 b 的 MAC 地址是 bb-bb-bb-bb-bb-bb,以此類推,不重複就好。

這樣,A 在發送數據包給 B 時,只要在頭部拼接一個這樣結構的數據,就能夠了。

B 在收到數據包後,根據頭部的目標 MAC 地址信息,判斷這個數據包的確是發給本身的,因而便收下

其餘的 CDE 收到數據包後,根據頭部的目標 MAC 地址信息,判斷這個數據包並非發給本身的,因而便丟棄

雖然集線器使整個佈局乾淨很多,但原來我只要發給電腦 B 的消息,如今卻要發給鏈接到集線器中的全部電腦,這樣既不安全,又不節省網絡資源。

 

第二層

 

若是把這個集線器弄得更智能一些,只發給目標 MAC 地址指向的那臺電腦,就行了。

雖然只比集線器多了這一點點區別,但看起來彷佛有智能了,你把這東西叫作交換機。也正由於這一點點智能,你把它放在了另外一個層級,數據鏈路層

 

 

 

如上圖所示,你是這樣設計的。

交換機內部維護一張 MAC 地址表,記錄着每個 MAC 地址的設備,鏈接在其哪個端口上。

MAC 地址 端口
bb-bb-bb-bb-bb-bb 1
cc-cc-cc-cc-cc-cc 3
aa-aa-aa-aa-aa-aa 4
dd-dd-dd-dd-dd-dd 5

假如你仍然要發給 B 一個數據包,構造了以下的數據結構從網口出去。

到達交換機時,交換機內部經過本身維護的 MAC 地址表,發現目標機器 B 的 MAC 地址 bb-bb-bb-bb-bb-bb 映射到了端口 1 上,因而把數據從 1 號端口發給了 B,完事~

你給這個經過這樣傳輸方式而組成的小範圍的網絡,叫作以太網

固然最開始的時候,MAC 地址表是空的,是怎麼逐步創建起來的呢?

假如在 MAC 地址表爲空是,你給 B 發送了以下數據

因爲這個包從端口 4 進入的交換機,因此此時交換機就能夠在 MAC地址表記錄第一條數據:

MAC:aa-aa-aa-aa-aa-aa-aa
端口:4

交換機看目標 MAC 地址(bb-bb-bb-bb-bb-bb)在地址表中並無映射關係,因而將此包發給了全部端口,也即發給了全部機器。

以後,只有機器 B 收到了確實是發給本身的包,因而作出了響應,響應數據從端口 1 進入交換機,因而交換機此時在地址表中更新了第二條數據:

MAC:bb-bb-bb-bb-bb-bb
端口:1

過程以下

 

 

通過該網絡中的機器不斷地通訊,交換機最終將 MAC 地址表創建完畢~

隨着機器數量越多,交換機的端口也不夠了,但聰明的你發現,只要將多個交換機鏈接起來,這個問題就垂手可得搞定~

你徹底不須要設計額外的東西,只須要按照以前的設計和規矩來,按照上述的接線方式便可完成全部電腦的互聯,因此交換機設計的這種規則,真的很巧妙。你想一想看爲何(好比 A 要發數據給 F)。

可是你要注意,上面那根紅色的線,最終在 MAC 地址表中可不是一條記錄呀,而是要把 EFGH 這四臺機器與該端口(端口6)的映射所有記錄在表中。

最終,兩個交換機將分別記錄 A ~ H 全部機器的映射記錄

左邊的交換機

MAC 地址 端口
bb-bb-bb-bb-bb-bb 1
cc-cc-cc-cc-cc-cc 3
aa-aa-aa-aa-aa-aa 4
dd-dd-dd-dd-dd-dd 5
ee-ee-ee-ee-ee-ee 6
ff-ff-ff-ff-ff-ff 6
gg-gg-gg-gg-gg-gg 6
hh-hh-hh-hh-hh-hh 6

右邊的交換機

MAC 地址 端口
bb-bb-bb-bb-bb-bb 1
cc-cc-cc-cc-cc-cc 1
aa-aa-aa-aa-aa-aa 1
dd-dd-dd-dd-dd-dd 1
ee-ee-ee-ee-ee-ee 2
ff-ff-ff-ff-ff-ff 3
gg-gg-gg-gg-gg-gg 4
hh-hh-hh-hh-hh-hh 6

這在只有 8 臺電腦的時候還好,甚至在只有幾百臺電腦的時候,都還好,因此這種交換機的設計方式,已經足足支撐一陣子了。

但很遺憾,人是貪婪的動物,很快,電腦的數量就發展到幾千、幾萬、幾十萬。

 

第三層

 

交換機已經沒法記錄如此龐大的映射關係了。

此時你動了歪腦筋,你發現了問題的根本在於,連出去的那根紅色的網線,後面不知道有多少個設備不斷地鏈接進來,從而使得地址表愈來愈大。

那我可不可讓那根紅色的網線,接入一個新的設備,這個設備就跟電腦同樣有本身獨立的 MAC 地址,並且同時還能幫我把數據包作一次轉發呢?

這個設備就是路由器,它的功能就是,做爲一臺獨立的擁有 MAC 地址的設備,而且能夠幫我把數據包作一次轉發你把它定在了網絡層。

注意,路由器的每個端口,都有獨立的 MAC 地址

好了,如今交換機的 MAC 地址表中,只須要多出一條 MAC 地址 ABAB 與其端口的映射關係,就能夠成功把數據包轉交給路由器了,這條搞定。

那如何作到,把發送給 C 和 D,甚至是把發送給 DEFGH.... 的數據包,通通先發送給路由器呢?

不難想到這樣一個點子,假如電腦 C 和 D 的 MAC 地址擁有共同的前綴,好比分別是

C 的 MAC 地址:FFFF-FFFF-CCCC
D 的 MAC 地址:FFFF-FFFF-DDDD

那咱們就能夠說,將目標 MAC 地址爲 FFFF-FFFF-?開頭的,通通先發送給路由器。

這樣是否可行呢?答案是否認的。

咱們先從現實中 MAC 地址的結構入手,MAC地址也叫物理地址、硬件地址,長度爲 48 位,通常這樣來表示

00-16-EA-AE-3C-40

它是由網絡設備製造商生產時燒錄在網卡的EPROM(一種閃存芯片,一般能夠經過程序擦寫)。其中前 24 位(00-16-EA)表明網絡硬件製造商的編號,後 24 位(AE-3C-40)是該廠家本身分配的,通常表示系列號。只要不更改本身的 MAC 地址,MAC 地址在世界是惟一的。形象地說,MAC地址就如同身份證上的身份證號碼,具備惟一性。

那若是你但願向上面那樣表示將目標 MAC 地址爲 FFFF-FFFF-?開頭的,統一從路由器出去發給某一羣設備(後面會提到這實際上是子網的概念),那你就須要要求某一子網下通通買一個廠商製造的設備,要麼你就須要要求廠商在生產網絡設備燒錄 MAC 地址時,提早按照你規劃好的子網結構來定 MAC 地址,而且往後這個網絡的結構都不能輕易改變。

這顯然是不現實的。

因而你發明了一個新的地址,給每一臺機器一個 32 位的編號,如:

11000000101010000000000000000001

你以爲有些不清晰,因而把它分紅四個部分,中間用點相連。

11000000.10101000.00000000.00000001

你還以爲不清晰,因而把它轉換成 10 進制。

192.168.0.1

最後你給了這個地址一個響亮的名字,IP 地址。如今每一臺電腦,同時有本身的 MAC 地址,又有本身的 IP 地址,只不過 IP 地址是軟件層面上的,能夠隨時修改,MAC 地址通常是沒法修改的。

這樣一個能夠隨時修改的 IP 地址,就能夠根據你規劃的網絡拓撲結構,來調整了。

如上圖所示,假如我想要發送數據包給 ABCD 其中一臺設備,不論哪一臺,我均可以這樣描述,"將 IP 地址爲 192.168.0 開頭的所有發送給到路由器,以後再怎麼轉發,交給它!",巧妙吧。

那交給路由器以後,路由器又是怎麼把數據包準確轉發給指定設備的呢?

別急咱們慢慢來。

咱們先給上面的組網方式中的每一臺設備,加上本身的 IP 地址

如今兩個設備之間傳輸,除了加上數據鏈路層的頭部以外,還要再增長一個網絡層的頭部。

假如 A 給 B 發送數據,因爲它們直接連着交換機,因此 A 直接發出以下數據包便可,其實網絡層沒有體現出做用。

但假如 A 給 C 發送數據,A 就須要先轉交給路由器,而後再由路由器轉交給 C。因爲最底層的傳輸仍然須要依賴以太網,因此數據包是分紅兩段的。

A ~ 路由器這段的包以下:

路由器到 C 這段的包以下:

好了,上面說的兩種狀況(A->B,A->C),相信細心的讀者應該會有很多疑問,下面咱們一個個來展開。

A 給 C 發數據包,怎麼知道是否要經過路由器轉發呢?

答案:子網

若是源 IP 與目的 IP 處於一個子網,直接將包經過交換機發出去。

若是源 IP 與目的 IP 不處於一個子網,就交給路由器去處理。

好,那如今只須要解決,什麼叫處於一個子網就行了。

  • 192.168.0.1 和 192.168.0.2 處於同一個子網

  • 192.168.0.1 和 192.168.1.1 處於不一樣子網

這兩個是咱們人爲規定的,即咱們想表示,對於 192.168.0.1 來講:

192.168.0.xxx 開頭的,就算是在一個子網,不然就是在不一樣的子網。

那對於計算機來講,怎麼表達這個意思呢?因而人們發明了子網掩碼的概念

假如某臺機器的子網掩碼定爲 255.255.255.0

這表示,將源 IP 與目的 IP 分別同這個子網掩碼進行與運算,相等則是在一個子網,不相等就是在不一樣子網,就這麼簡單。

好比

  • A電腦:192.168.0.1 & 255.255.255.0 = 192.168.0.0

  • B電腦:192.168.0.2 & 255.255.255.0 = 192.168.0.0

  • C電腦:192.168.1.1 & 255.255.255.0 = 192.168.1.0

  • D電腦:192.168.1.2 & 255.255.255.0 = 192.168.1.0

那麼 A 與 B 在同一個子網,C 與 D 在同一個子網,可是 A 與 C 就不在同一個子網,與 D 也不在同一個子網,以此類推。

因此若是 A 給 C 發消息,A 和 C 的 IP 地址分別 & A 機器配置的子網掩碼,發現不相等,則 A 認爲 C 和本身不在同一個子網,因而把包發給路由器,就無論了,以後怎麼轉發,A 不關心

A 如何知道,哪一個設備是路由器?

答案:在 A 上要設置默認網關

上一步 A 經過是否與 C 在同一個子網內,判斷出本身應該把包發給路由器,那路由器的 IP 是多少呢?

其實說發給路由器不許確,應該說 A 會把包發給默認網關

對 A 來講,A 只能直接把包發給同處於一個子網下的某個 IP 上,因此發給路由器仍是發給某個電腦,對 A 來講也不關心,只要這個設備有個 IP 地址就行。

因此默認網關,就是 A 在本身電腦裏配置的一個 IP 地址,以便在發給不一樣子網的機器時,發給這個 IP 地址。

僅此而已!

路由器如何知道C在哪裏?

答案:路由表

如今 A 要給 C 發數據包,已經能夠成功發到路由器這裏了,最後一個問題就是,路由器怎麼知道,收到的這個數據包,該從本身的哪一個端口出去,才能直接(或間接)地最終到達目的地 C 呢。

路由器收到的數據包有目的 IP 也就是 C 的 IP 地址,須要轉化成從本身的哪一個端口出去,很容易想到,應該有個表,就像 MAC 地址表同樣。

這個表就叫路由表

至於這個路由表是怎麼出來的,有不少路由算法,本文不展開,由於我也不會哈哈~

不一樣於 MAC 地址表的是,路由表並非一對一這種明確關係,咱們下面看一個路由表的結構。

目的地址 子網掩碼 下一跳 端口
192.168.0.0 255.255.255.0   0
192.168.0.254 255.255.255.255   0
192.168.1.0 255.255.255.0   1
192.168.1.254 255.255.255.255   1

咱們學習一種新的表示方法,因爲子網掩碼其實就表示前多少位表示子網的網段,因此如 192.168.0.0(255.255.255.0) 也能夠簡寫爲 192.168.0.0/24

目的地址 下一跳 端口
192.168.0.0/24   0
192.168.0.254/32   0
192.168.1.0/24   1
192.168.1.254/32   1

這就很好理解了,路由表就表示,192.168.0.xxx 這個子網下的,都轉發到 0 號端口,192.168.1.xxx 這個子網下的,都轉發到 1 號端口。下一跳列尚未值,咱們先無論

配合着結構圖來看(這裏把子網掩碼和默認網關都補齊了)

 

剛纔說的都是 IP 層,但發送數據包的數據鏈路層須要知道 MAC 地址,但是我只知道 IP 地址該怎麼辦呢?

答案:arp

假如你(A)此時不知道你同伴 B 的 MAC 地址(現實中就是不知道的,剛剛咱們只是假設已知),你只知道它的 IP 地址,你該怎麼把數據包準確傳給 B 呢?

答案很簡單,在網絡層,我須要把 IP 地址對應的 MAC 地址找到,也就是經過某種方式,找到 192.168.0.2 對應的 MAC 地址 BBBB

這種方式就是 arp 協議,同時電腦 A 和 B 裏面也會有一張 arp 緩存表,表中記錄着 IP 與 MAC 地址的對應關係。

IP 地址 MAC 地址
192.168.0.2 BBBB

一開始的時候這個表是空的,電腦 A 爲了知道電腦 B(192.168.0.2)的 MAC 地址,將會廣播一條 arp 請求,B 收到請求後,帶上本身的 MAC 地址給 A 一個響應。此時 A 便更新了本身的 arp 表。

這樣經過你們不斷廣播 arp 請求,最終全部電腦裏面都將 arp 緩存表更新完整。

 

總結一下

好了,總結一下,到目前爲止就幾條規則

從各個節點的視角來看

電腦視角

  • 首先我要知道個人 IP 以及對方的 IP

  • 經過子網掩碼判斷咱們是否在同一個子網

  • 在同一個子網就經過 arp 獲取對方 mac 地址直接扔出去

  • 不在同一個子網就經過 arp 獲取默認網關的 mac 地址直接扔出去

交換機視角:

  • 我收到的數據包必須有目標 MAC 地址

  • 經過 MAC 地址表查映射關係

  • 查到了就按照映射關係從個人指定端口發出去

  • 查不到就全部端口都發出去

路由器視角:

  • 我收到的數據包必須有目標 IP 地址

  • 經過路由表查映射關係

  • 查到了就按照映射關係從個人指定端口發出去(不在任何一個子網範圍,走其路由器的默認網關也是查到了)

  • 查不到則返回一個路由不可達的數據包

若是你嗅覺足夠敏銳,你應該能夠感覺到下面這句話:

網絡層(IP協議)自己沒有傳輸包的功能,包的實際傳輸是委託給數據鏈路層(以太網中的交換機)來實現的。

涉及到的三張表分別是

  • 交換機中有 MAC 地址表用於映射 MAC 地址和它的端口

  • 路由器中有路由表用於映射 IP 地址(段)和它的端口

  • 電腦和路由器中都有 arp 緩存表用於緩存 IP 和 MAC 地址的映射關係

這三張表是怎麼來的

  • MAC 地址表是經過以太網內各節點之間不斷經過交換機通訊,不斷完善起來的。

  • 路由表是各類路由算法 + 人工配置逐步完善起來的。

  • arp 緩存表是不斷經過 arp 協議的請求逐步完善起來的。

知道了以上這些,目前網絡上兩個節點是如何發送數據包的這個過程,就徹底能夠解釋通了!

 

 

 

 

那接下來咱們就放上本章 最後一個 網絡拓撲圖吧,請作好 戰鬥 準備!

這時路由器 1 鏈接了路由器 2,因此其路由表有了下一條地址這一個概念,因此它的路由表就變成了這個樣子。若是匹配到了有下一跳地址的一項,則須要再次匹配,找到其端口,並找到下一跳 IP 的 MAC 地址。

也就是說找來找去,最終必須能映射到一個端口號,而後從這個端口號把數據包發出去。

目的地址 下一跳 端口
192.168.0.0/24   0
192.168.0.254/32   0
192.168.1.0/24   1
192.168.1.254/32   1
192.168.2.0/24 192.168.100.5  
192.168.100.0/24   2
192.168.100.4/32   2

這時若是 A 給 F 發送一個數據包,能不能通呢?若是通的話整個過程是怎樣的呢?

 

思考一分鐘...

 

詳細過程動畫描述:

 

詳細過程文字描述:

1. 首先 A(192.168.0.1)經過子網掩碼(255.255.255.0)計算出本身與 F(192.168.2.2)並不在同一個子網內,因而決定發送給默認網關(192.168.0.254)

2. A 經過 ARP 找到 默認網關 192.168.0.254 的 MAC 地址。

3. A 將源 MAC 地址(AAAA)與網關 MAC 地址(ABAB)封裝在數據鏈路層頭部,又將源 IP 地址(192.168.0.1)和目的 IP 地址(192.168.2.2)(注意這裏千萬不要覺得填寫的是默認網關的 IP 地址,從始至終這個數據包的兩個 IP 地址都是不變的,只有 MAC 地址在不斷變化)封裝在網絡層頭部,而後發包

4. 交換機 1 收到數據包後,發現目標 MAC 地址是 ABAB,轉發給路由器1

5. 數據包來到了路由器 1,發現其目標 IP 地址是 192.168.2.2,查看其路由表,發現了下一跳的地址是 192.168.100.5

6. 因此此時路由器 1 須要作兩件事,第一件是再次匹配路由表,發現匹配到了端口爲 2,因而將其封裝到數據鏈路層,最後把包從 2 號口發出去。

7. 此時路由器 2 收到了數據包,看到其目的地址是 192.168.2.2,查詢其路由表,匹配到端口號爲 1,準備從 1 號口把數據包送出去。

8. 但此時路由器 2 須要知道 192.168.2.2 的 MAC 地址了,因而查看其 arp 緩存,找到其 MAC 地址爲 FFFF,將其封裝在數據鏈路層頭部,並從 1 號端口把包發出去。

9. 交換機 3 收到了數據包,發現目的 MAC 地址爲 FFFF,查詢其 MAC 地址表,發現應該從其 6 號端口出去,因而從 6 號端口把數據包發出去。

10. F 最終收到了數據包!而且發現目的 MAC 地址就是本身,因而收下了這個包

 

更詳細且精準的過程:

讀到這相信你們已經很累了,理解上述過程基本上網絡層如下的部分主流程就基本疏通了,若是你想要本過程更爲專業的過程描述,能夠在公衆號 低併發編程 後臺回覆 網絡,得到我模擬這個過程的 Cisco Packet Tracer 源文件。

每一步包的傳輸都會有各層的原始數據,以及專業的過程描述

 

 

同時在此基礎之上你也能夠設計本身的網絡拓撲結構,進行各類實驗,來加深網絡傳輸過程的理解。

 

後記

 

至此,通過物理層、數據鏈路層、網絡層這前三層的協議,以及根據這些協議設計的各類網絡設備(網線、集線器、交換機、路由器),理論上只要擁有對方的 IP 地址,就已經將地球上任意位置的兩個節點連通了。

本文通過了不少次的修改,刪減了很多影響主流程的內容,就是爲了讓讀者能抓住網絡傳輸前三層的真正核心思想。同時網絡相關的知識也是多且雜,我也還有不少搞不清楚的地方,很是歡迎你們與我交流,共同進步。

相關文章
相關標籤/搜索