在前兩篇文章中,我們完整的描述了計算機網絡 OSI 五層模型的相關內容。那么,本篇將會從一個實踐案例開始,帶你從整體上重新認識我們的計算機網絡。

我們以訪問 Google 為例,當我們在瀏覽器地址欄中敲下回車鍵之后,整個計算機網絡將會發生什么呢?
本機的網絡相關參數如下:

首先我們應用層的瀏覽器決定向 DNS 服務器請求解析域名「www.google.com」,那么就要遵循 DNS 協議。
DNS 運行在 53 號端口,於是瀏覽器會創建一個 UDP 套接字,標識該套接字的二元組分別是『目的 IP 地址』和『目的端口』。而套接字本質上就是為了唯一標識應用層進程,就是為了讓響應報文能夠找到目的地。
那么這里會創建一個 UDP 套接字,二元組為「本機 IP 地址 192.168.43.138」和「隨機產生一個未使用的端口號」。
接着,瀏覽器將 DNS 請求報文封裝好推入套接字,開始我們的 DNS 解析過程。
有關 DNS 的相關細節,這里不再贅述了,可以參考前面的文章,拿到 DNS 服務器的響應報文,運輸層拆開數據報,得到該報文的目的 IP 地址和目的端口號,於是對應着去找套接字交付報文即可。
最終我們會從『本地 DNS 服務器』得到 Google 的 IP 地址為:172.194.72.105。
整個 HTTP 請求可以說才剛剛開始:
應用層
瀏覽器封裝 HTTP 請求報文,然后創建一個 TCP 套接字,采用四元組標識,具體為「源 IP 地址:192.168.43.138」+「源端口號:隨機的,這里假設為 1234」+「目的 IP 地址:172.194.72.105」+「目的端口號:80」。
HTTP 報文也就是我們的應用層數據報,大致是這樣的:

指定了一些請求參數與動作,以及一些要求響應報文的返回格式要求,具體的我們不細說了。
緊接着,這個報文會被推進 TCP 套接字中,等待運輸層來收取。
運輸層
運輸層收取了報文,並判斷與目的主機是否建立了 TCP 連接,這里假設沒有。
那么,運輸層將不急着發送應用層數據,得先判斷與目的主機之間能夠正常通訊,也就是需要『握手』打招呼。
『三次握手』的相關細節,我們這里也不再贅述了,上篇文章描述的很詳細了,通過『三次握手』,發送端和接收端確認過發送與確認序號,分配了相應的緩存資源等。
一切准備就緒之后,運輸層將應用層發過來的數據報又一層封裝,添加進『源端口號』和『目的端口號』以及相關差錯檢驗字段。
最后將 TCP 數據報向下傳遞到網絡層。
網絡層
網絡層其實很簡單,拿到數據報並封裝成 IP 數據報,即在原 TCP 報文的前提之上添加『源 IP 地址』和『目的 IP 地址』等字段信息。
然后交由數據鏈路層。
鏈路層
數據鏈路層拿到 IP 數據報,它需要封裝成以太網幀才能在網絡中傳輸,也就是它需要目的主機的 Mac 地址,然而我們只知道目的主機的 IP 地址。
所以,鏈路層有一個 ARP 協議,直接或間接的能夠根據目的 IP 地址獲得使用該 IP 地址的主機 Mac 地址。
當然,ARP 協議運行的前提是,目的 IP 地址和當前發送方主機處於同一子網絡中。如果不然,發送方將目的 Mac 地址填自己網關路由的 Mac 地址,然后通過物理層發送出去。
網關路由由於具有轉發表和路由選擇算法,所以它知道目的網絡該怎么到達,所以一路轉發,最終會發送到目的網絡的網關路由上。
最后,目的網絡的網關路由同樣會經由 ARP 協議,取得目的主機的 Mac 地址,然后廣播發送,最后被目的主機接受。
這樣谷歌的服務器就接受到一個 HTTP 請求,於是它解析這個請求,確定該請求的動作是什么,也就是它需要什么東西,並構建響應報文,以同樣的方式從網絡到達源主機。
最后你將看到你想要的谷歌搜索頁面:

整體上我們自頂而下的描述了一個請求到達目的地的完整過程,旨在宏觀上建立完整的框架體系,相關細節之處可以參照前兩篇文章。
文章中的所有代碼、圖片、文件都雲存儲在我的 GitHub 上:
(https://github.com/SingleYam/overview_java)
歡迎關注微信公眾號:撲在代碼上的高爾基,所有文章都將同步在公眾號上。

