網絡協議必會知識點:互聯網網絡分層

文章出自 |《趣談網絡協議》

長時間從事計算機網絡相關的工作,我發現,計算機網絡有一個顯著的特點,就是這是一個不僅需要背誦,而且特別需要將原理爛熟於胸的學科。很多問題看起來懂了,但是就怕往細裏問,一問就發現你懂得沒有那麼透徹。

我們上一節列了之後要講的網絡協議。這些協議本來沒什麼稀奇,每一本教科書都會講,並且都要求你背下來。因爲考試會考,面試會問。可以這麼說,畢業了去找工作還答不出這類題目的,那你的筆試基本上也就掛了。

當你聽到什麼二層設備、三層設備、四層LB和七層LB中層的時候,是否有點一頭霧水,不知道這些所謂的層,對應的各種協議具體要做什麼“工作”?

這四個問題你真的懂了嗎?

因爲教科書或者老師往往會打一個十分不恰當的比喻:爲什麼網絡要分層呀?因爲不同的層次之間有不同的溝通方式,這個叫作協議。例如,一家公司也是分“層次”的,分總經理、經理、組長、員工。總經理之間有他們的溝通方式,經理和經理之間也有溝通方式,同理組長和員工。有沒有聽過類似的比喻?

那麼第一個問題來了。請問經理在握手的時候,員工在幹什麼?很多人聽過TCP建立連接的三次握手協議,也會把它當知識點背誦。同理問你,TCP在進行三次握手的時候,IP層和MAC層對應都有什麼操作呢?

除了上面這個不恰當的比喻,教科書還會列出每個層次所包含的協議,然後開始逐層地去講這些協議。但是這些協議之間的關係呢?卻很少有教科書會講。

學習第三層的時候會提到,IP協議裏面包含目標地址和源地址。第三層裏往往還會學習路由協議。路由就像中轉站,我們從原始地址A到目標地址D,中間經過兩個中轉站A->B->C->D,是通過路由轉發的。

那麼第二個問題來了。A知道自己的下一個中轉站是B,那從A發出來的包,應該把B的IP地址放在哪裏呢?B知道自己的下一個中轉站是C,從B發出來的包,應該把C的IP地址放在哪裏呢?如果放在IP協議中的目標地址,那包到了中轉站,怎麼知道最終的目的地址是D呢?

教科書不會通過場景化的例子,將網絡包的生命週期講出來,所以你就會很困惑,不知道這些協議實際的應用場景是什麼。

我再問你一個問題。你一定經常聽說二層設備、三層設備。二層設備處理的通常是MAC層的東西。那我發送一個HTTP的包,是在第七層工作的,那是不是不需要經過二層設備?或者即便經過了,二層設備也不處理呢?或者換一種問法,二層設備處理的包裏,有沒有HTTP層的內容呢?

最終,我想問你一個綜合的問題。從你的電腦,通過SSH登錄到公有云主機裏面,都需要經歷哪些過程?或者說你打開一個電商網站,都需要經歷哪些過程?說得越詳細越好。

實際情況可能是,很多人會答不上來。儘管對每一層都很熟悉,但是知識點卻串不起來。

上面的這些問題,有的在這一節就會有一個解釋,有的則會貫穿我們整個課程。好在後面一節中我會舉一個貫穿的例子,將很多層的細節講過後,你很容易就能把這些知識點串起來。

網絡爲什麼要分層?

這裏我們先探討第一個問題,網絡爲什麼要分層?因爲,是個複雜的程序都要分層。

理解計算機網絡中的概念,一個很好的角度是,想象網絡包就是一段Buffer,或者一塊內存,是有格式的。同時,想象自己是一個處理網絡包的程序,而且這個程序可以跑在電腦上,可以跑在服務器上,可以跑在交換機上,也可以跑在路由器上。你想象自己有很多的網口,從某個口拿進一個網絡包來,用自己的程序處理一下,再從另一個網口發送出去。

當然網絡包的格式很複雜,這個程序也很複雜。複雜的程序都要分層,這是程序設計的要求。比如,複雜的電商還會分數據庫層、緩存層、Compose層、Controller層和接入層,每一層專注做本層的事情。

程序是如何工作的?

我們可以簡單地想象“你”這個程序的工作過程。

當一個網絡包從一個網口經過的時候,你看到了,首先先看看要不要請進來,處理一把。有的網口配置了混雜模式,凡是經過的,全部拿進來。

拿進來以後,就要交給一段程序來處理。於是,你調用process_layer2(buffer)。當然,這是一個假的函數。但是你明白其中的意思,知道肯定是有這麼個函數的。那這個函數是幹什麼的呢?從Buffer中,摘掉二層的頭,看一看,應該根據頭裏面的內容做什麼操作。

假設你發現這個包的MAC地址和你的相符,那說明就是發給你的,於是需要調用process_layer3(buffer)。這個時候,Buffer裏面往往就沒有二層的頭了,因爲已經在上一個函數的處理過程中拿掉了,或者將開始的偏移量移動了一下。在這個函數裏面,摘掉三層的頭,看看到底是發送給自己的,還是希望自己轉發出去的。

如何判斷呢?如果IP地址不是自己的,那就應該轉發出去;如果IP地址是自己的,那就是發給自己的。根據IP頭裏面的標示,拿掉三層的頭,進行下一層的處理,到底是調用process_tcp(buffer)呢,還是調用process_udp(buffer)呢?

假設這個地址是TCP的,則會調用process_tcp(buffer)。這時候,Buffer裏面沒有三層的頭,就需要查看四層的頭,看這是一個發起,還是一個應答,又或者是一個正常的數據包,然後分別由不同的邏輯進行處理。如果是發起或者應答,接下來可能要發送一個數據包;如果是一個正常的數據包,就需要交給上層了。交給誰呢?是不是有process_http(buffer)函數呢?

沒有的,如果你是一個網絡包處理程序,你不需要有process_http(buffer),而是應該交給應用去處理。交給哪個應用呢?在四層的頭裏面有端口號,不同的應用監聽不同的端口號。如果發現瀏覽器應用在監聽這個端口,那你發給瀏覽器就行了。至於瀏覽器怎麼處理,和你沒有關係。

瀏覽器自然是解析HTML,顯示出頁面來。電腦的主人看到頁面很開心,就點了鼠標。點擊鼠標的動作被瀏覽器捕獲。瀏覽器知道,又要發起另一個HTTP請求了,於是使用端口號,將請求發給了你。

你應該調用send_tcp(buffer)。不用說,Buffer裏面就是HTTP請求的內容。這個函數裏面加一個TCP的頭,記錄下源端口號。瀏覽器會給你目的端口號,一般爲80端口。

然後調用send_layer3(buffer)。Buffer裏面已經有了HTTP的頭和內容,以及TCP的頭。在這個函數裏面加一個IP的頭,記錄下源IP的地址和目標IP的地址。

然後調用send_layer2(buffer)。Buffer裏面已經有了HTTP的頭和內容、TCP的頭,以及IP的頭。這個函數裏面要加一下MAC的頭,記錄下源MAC地址,得到的就是本機器的MAC地址和目標的MAC地址。不過,這個還要看當前知道不知道,知道就直接加上;不知道的話,就要通過一定的協議處理過程,找到MAC地址。反正要填一個,不能空着。

萬事俱備,只要Buffer裏面的內容完整,就可以從網口發出去了,你作爲一個程序的任務就算告一段落了。

揭祕層與層之間的關係

知道了這個過程之後,我們再來看一下原來困惑的問題。

首先是分層的比喻。所有不能表示出層層封裝含義的比喻,都是不恰當的。總經理握手,不需要員工在吧,總經理之間談什麼,不需要員工參與吧,但是網絡世界不是這樣的。正確的應該是,總經理之間溝通的時候,經理將總經理放在自己兜裏,然後組長把經理放自己兜裏,員工把組長放自己兜裏,像套娃娃一樣。那員工直接溝通,不帶上總經理,就不恰當了。

現實生活中,往往是員工說一句,組長補充兩句,然後經理補充兩句,最後總經理再補充兩句。但是在網絡世界,應該是總經理說話,經理補充兩句,組長補充兩句,員工再補充兩句。

那TCP在三次握手的時候,IP層和MAC層在做什麼呢?當然是TCP發送每一個消息,都會帶着IP層和MAC層了。因爲,TCP每發送一個消息,IP層和MAC層的所有機制都要運行一遍。而你只看到TCP三次握手了,其實,IP層和MAC層爲此也忙活好久了。

這裏要記住一點:只要是在網絡上跑的包,都是完整的。可以有下層沒上層,絕對不可能有上層沒下層。

所以,對TCP協議來說,三次握手也好,重試也好,只要想發出去包,就要有IP層和MAC層,不然是發不出去的。

經常有人會問這樣一個問題,我都知道那臺機器的IP地址了,直接發給他消息唄,要MAC地址幹啥?這裏的關鍵就是,沒有MAC地址消息是發不出去的。

所以如果一個HTTP協議的包跑在網絡上,它一定是完整的。無論這個包經過哪些設備,它都是完整的。

所謂的二層設備、三層設備,都是這些設備上跑的程序不同而已。一個HTTP協議的包經過一個二層設備,二層設備收進去的是整個網絡包。這裏面HTTP、TCP、 IP、 MAC都有。什麼叫二層設備呀,就是隻把MAC頭摘下來,看看到底是丟棄、轉發,還是自己留着。那什麼叫三層設備呢?就是把MAC頭摘下來之後,再把IP頭摘下來,看看到底是丟棄、轉發,還是自己留着。

小結

總結一下今天的內容,理解網絡協議的工作模式,有兩個小竅門:

  • 始終想象自己是一個處理網絡包的程序:如何拿到網絡包,如何根據規則進行處理,如何發出去;
  • 始終牢記一個原則:只要是在網絡上跑的包,都是完整的。可以有下層沒上層,絕對不可能有上層沒下層。

我是劉超,歡迎你訂閱我的專欄《趣談網絡協議》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章