一個數(shù)據(jù)包的互聯(lián)網(wǎng)漫游記
盡管大多數(shù)最終用戶都不關心 Internet 是如何工作的,但是我相信你們當中的仍然會有一些人對 Internet 運轉(zhuǎn)的基本原理非常感興趣。
在這篇文章中,我們會通過闡釋一個數(shù)據(jù)包從源到目的地的征程,來試著撥開互聯(lián)網(wǎng)的***層神秘面紗。由此出發(fā),我們會盡量讓本文的內(nèi)容保持簡單基礎。
在更進一步之前,讓我們先快速簡要地理解一下 DHCP 和 DNS 的概念。
DHCP
你有沒有想過你的計算機是如何獲取 IP 地址的?嗯……首先你必須知道計算機獲取 IP 地址是有兩種途徑的,一種是靜態(tài)方式,另一種是動態(tài)方式。
靜態(tài)方式就是由管理員在機器上手動設置 IP 地址。如果你的計算機連接在局域網(wǎng)或者類似的網(wǎng)絡上的話,需要注意的是你所設置的 IP 地址不能和網(wǎng)絡上任何其他機器的 IP 地址相同,因為那樣會引起 IP 地址沖突,兩臺機器就都不能連接到 Internet 了。
動態(tài)方式就是計算機(在系統(tǒng)啟動的時候)請求一臺服務器來為它分配一個 IP 地址。這一過程使用的協(xié)議稱為動態(tài)主機配置協(xié)議(DHCP)。這里提到的服務器就是 DHCP 服務器,這臺服務器負責為網(wǎng)絡上所有的計算機分配 IP 地址。此時由 DHCP 來保證沒有 IP 地址沖突。如果一臺機器關閉繼而重啟,那么一條刷新 DHCP 的請求就發(fā)送到 DHCP 服務器上,這一次可能會分配給它一臺與原來相同或者不同的 IP 地址。通常 DHCP 服務器會得到一個 IP 地址池,DHCP 服務器只能分配該地址池內(nèi)的地址。這么做是為了保證將其他 IP 地址作為靜態(tài)地址的時候不會引起任何沖突。
DNS
我們大多數(shù)人都使用過 google.com 進行搜索,不過你有沒有想過為什么在瀏覽器里面輸入 google.com 就能連接到 Google 的服務器呢?嗯……要理解這件事情,我們需要理解域名服務器(DNS)的概念。
就如同現(xiàn)實生活中人們通過名字互相區(qū)分一樣,在計算機網(wǎng)絡的世界里,不同的計算機之間通過指派給它們的 IP 地址來互相區(qū)分。IP 地址有兩種類型:公有和私有。通常服務器使用公有地址,這是因為他們要被全世界數(shù)以百萬計的計算機訪問。至于你那連接在路由器上的個人電腦,它通常獲取到的是私有 IP。由于公有地址的數(shù)量是有限的,所以現(xiàn)在搭設局域網(wǎng)(在一個有著公有 IP 的路由下搭建)然后使用私有地址開始變得流行并且非常成功。
記憶 IP 地址這樣的任務對于大多數(shù)人來說有些困難,于是每個服務器都還有一個名字(比如 google.com)。這樣最終用戶只需要記住這個名字,在瀏覽器中輸入它,然后敲回車就可以了?,F(xiàn)在讓我來看看當用戶在瀏覽器中輸入名字并敲回車之后究竟發(fā)生了什么。首先,需要把域名轉(zhuǎn)換成對應的 IP。要完成這項任務,需要給默認網(wǎng)關(大多數(shù)情況下就是路由器)發(fā)送一條與 DNS 請求。路由都會配置一個 DNS 服務器地址,這個地址便是 DNS 請求的目的地。
DNS 服務器用來將域名轉(zhuǎn)換成 IP 地址。當 DNS 服務器收到一條請求后,它會檢查它有沒有該請求需要的轉(zhuǎn)換信息。如果沒有這條轉(zhuǎn)換信息,那么 DNS 服務器會把這條請求轉(zhuǎn)發(fā)給其他的 DNS 服務器。通過這種方式,就完成了從域名到 IP 地址的轉(zhuǎn)換。轉(zhuǎn)換結果隨后會發(fā)回到發(fā)出請求的計算機。
DNS 之后又發(fā)生了些些什么?
要理解下面的解釋,你應該對 TCP/IP 協(xié)議族有一定的了解。當然啦,我們會盡量保持解釋的簡單性。
* 一旦通過 DNS 得到了目標 IP 地址,應用層就會準備好一條 HTTP GET 請求。隨后這條請求會前進到傳輸層。
* 這一層有兩個主要的協(xié)議——TCP 和 UDP。正是在這一層,該請求被封裝為了傳輸層數(shù)據(jù)包。如果用的是 TCP 協(xié)議,還要保證包的大小不能超過源和目的地之間 MTU(***傳輸單元)的最小值。這樣做的目的是避免數(shù)據(jù)包在傳輸過程中分片(fragmentation)。另一方面,如果用的 UDP 的話,就不用顧慮這么多了,當然了這種情況下,包就有可能分片了。
* 一旦傳輸層的包封好了,接著它就會被推到 IP 層。這一層會增加源和目的地的 IP 地址以及一些其他有用的信息,諸如 TTL(time to live 生存期)、分段信息等等。所有的這些信息在數(shù)據(jù)包抵達目的地的路途中都是有用的。
* 當數(shù)據(jù)包進入到數(shù)據(jù)鏈路層之后,與 MAC 地址相關的信息就會加諸其上,隨后數(shù)據(jù)包就會被推送到物理層。這樣一串“0”和“1”就會從你的網(wǎng)卡里發(fā)送到物理媒介中去。
如果數(shù)據(jù)包的目的地沒有直接連接在源計算機上,那么根據(jù)源計算機上存儲的路由信息,數(shù)據(jù)包就會傳送到最近的網(wǎng)絡節(jié)點上去。網(wǎng)絡中有各種不同的節(jié)點,比如路由、網(wǎng)橋、網(wǎng)關等等。每一種都有重要的作用,例如路由用來傳送 IP 包,網(wǎng)橋用來連接不同協(xié)議的異構網(wǎng)絡。
* 如果我們考慮一個簡單的網(wǎng)絡的話,路由就是將數(shù)據(jù)包從源送到目的地的最主要的角色。數(shù)據(jù)包離開源計算機后,與其相連的路由(數(shù)據(jù)要先發(fā)送到這里)的 MAC 地址就這個包的目的 MAC 地址。
數(shù)據(jù)包到達該路由之后,路由就會做下面幾件事情:
* 減記 TTL 值,重新計算數(shù)據(jù)包的校驗和。
* 搜索其路由表,以檢查其中有沒有數(shù)據(jù)包的目的 IP 所對應的主機。如果有的,路由就將該包發(fā)到相應的主機。
* 如果沒有這樣的一條路由,就從路由表中搜索源于該目的 IP 的網(wǎng)絡的地址。如果有的話就將該包發(fā)送到這個特定的網(wǎng)絡。
* 如果上面的兩次搜索都失敗的話,該數(shù)據(jù)包就被發(fā)送到路由表中指定的默認路由。
上面的所有情況中,不論數(shù)據(jù)包是在路由之間傳送還是從路由傳送到目的地,目的 MAC 地址都會變成最近的路由或者目的地的 MAC 地址。通過這種方式,目的 IP 地址保持不變,而目的 MAC 地址不斷從一個路由變?yōu)榱硪粋€。就是這樣,數(shù)據(jù)包從一臺路由到下一臺路由,直到它抵達終點。
啊哈,千難萬險之后我們的 HTTP GET 請求終于到達目的地啦:
* 數(shù)據(jù)包首先抵達物理層,該層向 CPU 發(fā)送一個 IRQ 來告訴 CPU 有數(shù)據(jù)到了,需要處理。
* 當數(shù)據(jù)被送到數(shù)據(jù)鏈路層后,就會檢查它的 MAC 地址來確認該數(shù)據(jù)包確實發(fā)到這臺計算機的。
* 如果上述檢查通過的話,數(shù)據(jù)包就會傳到 IP 層。在這里會檢查數(shù)據(jù)包的 IP 地址以及其校驗和,隨后將其傳送到相應的傳輸層。
* 這些都完成了之后,該信息(在我們的例子里是 HTTP GET 請求)就會根據(jù)端口的值被送到監(jiān)聽該端口的應用中去。
* 我們的請求就是這樣送抵 Google 的網(wǎng)絡服務器的。
之后,相應的響應會以與上述相同的方式傳送回來。
現(xiàn)在你都了解了,這就是數(shù)據(jù)包在 Internet 上從源到目的地的旅程。