上篇文章 咱們完整的描述了計算機五層模型中的『應用層』和『運輸層』,闡述了較爲複雜的 TCP 協議的相關原理,相信你們必定也有所收穫,那麼本篇將繼續五層模型的學習。java
『網絡層』其實解決的就是一個「轉發」的問題,經過傳說中的『IP 協議』劃分了網絡範圍,即我沒有直接用網線和你連在一塊兒,我也能經過你的 IP 分析出該怎麼樣找到負責你的網關路由器,並經過你的網關路由給你傳輸數據報。git
這就是『網絡層』作的事情,它本質上解決了兩臺不存在於同一子網絡下的主機相互通訊的問題。而『IP 協議』以及「如何解析 IP 的算法」算是兩個最核心的內容,咱們首先看看這個『IP 協議』的相關概念。github
以 IPv4 爲例,使用 32 個比特位描述一個 IP 地址,因此理論上,整個 IPv4 能夠提供 40 幾個億的 IP 地址,咱們通常使用『點分十進制』來表示。算法
例如:11000001 00100000 11011000 00001001 的 IP 地址通常記爲 193.32.216.9。bash
由此,咱們解決了 IP 編址的問題,可是如何經過 IP 地址判斷出它所屬的子網絡呢?服務器
引入一個名詞『子網掩碼』,它在形式上和 IP 地址同樣,使用 32 位比特位進行表述。其中,描述網絡部分的比特位全爲 1,子網絡中的該主機編號部分全爲 0 。微信
例如:子網掩碼 11111111.11111111.11111111.00000000,寫成十進制就是255.255.255.0。它明確了某個使用該子網掩碼的 IP 的前 24 位是它的子網絡部分,然後 8 位是該 IP 對應的主機在子網絡下的一個編號。網絡
舉個例子:post
IP 地址 172.16.254.1 所對應的子網掩碼爲 255.255.255.0,那麼咱們只須要作『AND』運算這二者便可獲得該 IP 地址的網絡部分。學習
因此,這個 IP 地址的網絡號爲 172.16.254 。
下面咱們探討一個十分重要的協議,它解決了一個剛加入子網絡的主機如何獲取屬於它的 IP 地址的問題,這個協議叫,動態主機配置協議(DHCP)。
DHCP
通常來講,咱們有兩種方式來配置主機的 IP 地址,一種是管理員手動的指定一個 IP 地址,固然,這樣的成本是很是高的,你不能配置了一個已經被分配出去的 IP地址,即管理員須要記錄全部已分配的 IP 地址。
另一種呢,就是咱們的 DHCP 協議,它容許新加入的主機自動獲取一個 IP 地址以及相關的子網掩碼和網關地址等。
默認狀況下,路由器隔離廣播包,不會將收到的廣播包從一個子網發送到另外一個子網。當 DHCP 服務器和客戶端不在同一個子網時,充當客戶端默認網關的路由器將廣播包發送到DHCP服務器所在的子網,這一功能就稱爲 DHCP 中繼(DHCP Relay)。
也就是說,一個子網絡中應當有一臺 DHCP 服務器,用於整個子網中 IP 地址的分配。但爲每一個子網都單獨配置一個 DHCP 服務器也有點「愚蠢」。
因此另外一種解決辦法就是,某個網絡中的網關會知道負責該網絡的 DHCP 服務器在什麼位置,IP 地址是什麼,網關路由會負責轉發 DHCP 報文請求並返回響應的報文,這就叫 DHCP 中繼。
固然了,實際上如今的路由器自己就能夠充當一個 DHCP 服務器,爲其所在的子網提供動態地址獲取服務,因此每每也不須要轉發那樣麻煩。
而完整的 DHCP 請求與響應的過程則是這樣的:
第一步:
DHCP 服務器發現。 這個階段的首要任務是,找到當前網絡中 DHCP 服務器的位置,而且整個 DHCP 報文的交換是基於 UDP/IP 協議的,向目的端口 67 發送。
本機因爲沒有 IP 地址,因此 IP 數據報中的『源地址』爲「0.0.0.0」,『目的地址』爲「255.255.255.255」。
這樣在鏈路層廣播該數據報的時候,同一子網絡下的全部主機都會接受該數據報,但只有 DHCP 服務器會響應這個請求。
因而若是路由器自己就是一個 DHCP 服務器的話,那將進入第二步,不然路由器將分組轉發到 DHCP 服務器所在的網絡內。
第二步:
DHCP 服務器提供。 DHCP 服務器,不管是位於外網或是網關路由自己,在收到一個『發現報文』後,將響應一個『提供報文』。
該報文中將包含,推薦客戶使用的 IP 地址、子網掩碼、IP 地址租用週期等信息。
第三步:
DHCP 請求。這實際上是一個選擇階段,客戶端主機確認服務器推薦的參數,決定使用,因而依然以廣播的形式發送請求向服務器確認。
第四步:
DHCP ACK。收到客戶端主機發來的確認請求後,服務器將實際從 IP 池中分配出一塊 IP 地址出來,並返回客戶端確認信息的 ACK。
今後以後,該主機算是得到了一塊可用的 IP 地址了,終於加入了網絡。
除此以外,還有一個細節不知道你們平常有沒有留心,就是咱們對於同一個子網絡,IP 地址基本老是同樣的,並無由於每次開機後連入網絡而被分配不一樣的 IP。
這一點算是 DHCP 協議的一個約定了,當某臺主機第一次加入某個子網絡,它將從 DHCP 服務器獲取一個全新的 IP 地址。
而之後該主機從新加入到該網絡時,將直接進入 DHCP 請求的第三步,將主機上次使用的參數發給服務器,確認是否可用。而通常狀況下服務器會贊成並按照你的要求分配出去一塊 IP 地址,這也是爲何你每次使用的幾乎是同一 IP。
講完了 DHCP 動態獲取 IP 地址,接着咱們簡單看看 IP 數據報的基本格式,並在最後討論一下路由器的選擇算法,看看一個 IP 數據報是如何被路由器給轉發出去的。
關於其中的各個字段或選項是如何被使用的,咱們這裏暫時先不作討論,強行解釋並適合你們理解,等到具體分析報文分發與解析時會容易理解不少。
路由器
路由器是網絡層的一個核心設備,它完成了從「目的 IP 地址」到「目的 IP 所在的子網絡」的完整路徑轉發過程。它的內部結構以下:
每一個端口都直接鏈接了一臺設備,而其中的『路由選擇處理器』則負責解析一個輸入端口進來的數據應該被推出到哪一個輸出端口中去。
因此,你應該也發現了,整個路由器的核心應該是這個『路由選擇處理器』,也就是驅動這個『路由選擇處理器』工做的算法,咱們稱之爲『路由選擇算法』。算法本質上就是解決,一個數據報輸入進路由器內存,該從哪一個輸出口轉發出去的問題。
一個好的 『路由選擇算法』不只僅應該解決如何到達目的地的問題,還應該考慮如何最快的到達目的地,即可以判斷並選擇性的繞過擁塞的網絡路徑。
整個路由選擇算法分爲兩大類,全局式路由選擇算法和分散式路由選擇算法。前者的一個最典型的實現就是『鏈路狀態路由選擇算法』,後者的一個最典型的實現就是『距離向量算法』。
這二者算法的理論原理這裏再也不和你們一塊兒探討了,咱們着重看看因特網中是如何基於這兩種算法實現的路由選擇。
首先,整個因特網是一個很龐大且複雜的系統,因此總體上被劃分爲一個一個的自治系統(AS),在每個 AS 中都運行着一樣的路由算法,自治系統之間使用 BGP 協議交換信息。
整個因特網大體就是這樣的一個個自治系統互聯構成的,而自治系統內部的全部路由器都運行着一樣的路由選擇算法,基於距離向量的『RIP 協議』或基於鏈路狀態的『OSPF 協議』。
至於爲何要拆分自治系統,等咱們介紹完這個 RIP 或者 OSPF,你就明白了。
RIP 協議的算法是這樣的:
簡單的一個自治系統,咱們以此爲例看看整個 RIP 協議是如何工做的。
首先最開始,路由器 A 的轉發表確定是這樣的:
----------------------------
目的子網 下一跳路由 跳數
x B 1
q E 1
----------------------------
複製代碼
其餘路由器也是相似的,第一步都創建起與本身直接相連鄰居的鏈接。
第二步是一個不斷進行的過程,相鄰的路由器之間每隔 30 秒就相互交換信息,告知對方本身的轉發表內容。
因此通過一次交換以後,路由器 A 將收到來自 B 和 E 的轉發表信息,因而路由轉發表更新以下:
----------------------------
目的子網 下一跳路由 跳數
x B 1
q E 1
y B 2
p E 2
----------------------------
複製代碼
可是這裏有一個細節,子網絡 y 是能夠經過 A - B - y 到達的,但同時也能夠經過 A - E - C - y 到達。你也許已經猜到了,路由器固然會選擇最短路徑的一條來更新本身的轉發表。
因此,這個距離向量的算法本質上就是經過相互之間不斷的交換信息以保證某個自治系統內,全部的路由器都知道某個目的子網的最短路徑。
OSPF 的實現是這樣的:
咱們一樣以上面的例子進行解釋:
OSPF 是基於鏈路狀態路由選擇算法進行實現的,因此它也是一個全局性路由選擇算法,算法運行一次便可完成全網的路由信息更新。
而 OSPF 本質上就是一個迪傑斯特拉求最短路徑問題,它經過不斷的迭代與計算更新整個路由轉發表。假設如今咱們的路由器 A 運行 OSPF 協議:
第一次迭代完成後,它獲得與 B、E 兩臺路由器相關的子網絡的路徑計算。
第二次以 B 或者 E 爲起點從新運行算法,這裏咱們假設以 B 爲起點運行了算法,那麼與 C 相關的子網絡的路徑也被更新進 A 的路由轉發表。
第三次以 C 爲起點一樣的運行算法,獲得和 D 相關的子網絡路徑更新。
因爲 D 做爲末端路由,並無直接相連的其餘路由,因此算法再也不繼續,回到 E。
第四次,以 E 做爲原點,運行算法,獲得了 C 相關子網絡的路徑,若是有更短的路徑,將更新 A 的轉發表以最優路徑。
那麼,待整個算法運行結束,一個自治系統中的全部路由器幾乎所有遍歷,可是卻不一樣於 RIP,OSPF 相對而言收斂快,能夠迅速完成任務,而 RIP 則須要不斷的交換信息以達到需求,每每會陷入一個長週期。
固然了,OSPF 須要較強的 CPU 計算能力和更多的內存存儲空間。因此總的而言,他們都普遍應用於整個因特網之中,RIP 應用在較爲底層的 ISP 上,而 OSPF 則運行在較爲高級的 ISP 中。
至此,整個網絡層的基本內容也介紹完了,總結一下,網絡層的核心任務就是負責轉發分組,而如何將分組轉發到目的主機的網絡中呢,牽扯出 IP 協議,經過 IP 地址與子網掩碼劃分子網絡,而路由器執行路由選擇算法得知目的子網絡的完整路由路徑並進行分發。
網絡層解決的是,分組轉發的目的網絡,也就是轉發給目的網絡的網關路由,而鏈路層解決的是,將分組廣播給我的,也即目的主機。
網絡層的 IP 數據包會在鏈路層被封裝成『以太網幀』,它的基本結構是這樣的:
前導碼用於同步時鐘,按照個人理解就是區分一個一個的幀,源和目的地址指的是『Mac 地址』,也稱做物理地址。
『Mac 地址』是硬件級別的主機惟一標識,由生產廠家惟一肯定。相似這樣:
34-E6-AD-17-A5-6B
全球任意一臺主機的 Mac 地址都是不一樣的,它不像 IP 地址能夠在別人不用的時候共享。
下面咱們要講一個協議,它完成了主機 IP 地址到 Mac 地址的轉換,他就是 ARP 地址解析協議。
ARP 協議其實有點相似於咱們之間在應用層介紹的 DNS 協議,輸入一個域名 地址,輸出一個 IP 地址,而 ARP 而言,輸入一個 IP 地址,輸出一個 Mac 地址。
網絡中的每臺主機,包括路由器,都內置的 ARP 模塊和 ARP 表。當一份數據報到達鏈路層時,首先要作的就是以該數據報的目的 IP 做爲輸入,先查詢本身主機的 ARP 模塊,若是可以獲得該 IP 的目的主機 Mac 地址,那麼封裝一個以太網幀交給物理層發送出去就好。
而若是本機的 ARP 表中並無存儲目的 IP 主機的 Mac 地址,那麼就須要向同網絡中的其餘主機進行查詢。
發送方會構建一個特殊的 ARP 分組,源 Mac 地址爲發送方的 Mac 地址,目的 Mac 地址爲廣播地址:255.255.255.255,以及源和目的 IP 地址,本質上就是一個特殊的以太網幀。
因而該網絡下的全部主機都將收到這個 ARP 分組,那麼他們要作的就是拆開 IP 地址比對是否和本身的 IP 地址相同,若是是則響應一個 ARP 分組,告訴發送方本身的 Mac 地址。
若是不是本身,則還會檢查本身的 ARP 模塊,看看是否能提供幫助。
最終,發送方會獲得想要的目的 Mac 地址並更新本身的 ARP 表,而後封裝一個正常的以太網幀發送出去。
因爲以太網採起的是『廣播』方式,因此同一子網絡中任意一臺主機發送報文,全部的其他主機都會收到,可是它們會匹配目的 Mac 地址是不是本身,不是則丟棄,這一點很重要。
好了,那麼到此爲止咱們也簡單介紹了鏈路層的相關內容,關於物理層,其實沒什麼介紹的,就是 0、1 的電信號傳輸。
關於整個 OSI 五層模型,咱們從上至下也已經完成了學習,下一篇將完整的看看 「www.baidu.com」以後,整個計算機網絡發生的故事,其實有點標題黨了,最後一篇才介紹完整的 HTTP 請求過程,見諒!
文章中的全部代碼、圖片、文件都雲存儲在個人 GitHub 上:
(https://github.com/SingleYam/overview_java)
歡迎關注微信公衆號:撲在代碼上的高爾基,全部文章都將同步在公衆號上。