序言:做開發已經有幾年了,但是面對兩臺機器的互動,只是略微知道一點,一臺機器根據URL傳送請求,伺服器進行響應,更細緻的互動模型,以及底層的一些處理根本不瞭解,我決定細緻的探究一下網路協議
概述
網際網路的本質其實就是一系列的網路協議,標準的網路模型稱為 OSI模型—開放式系統互聯通訊參考模型,該模型將網路通訊的工作分為七層。
但是由於OSI模型作為計算機網路通訊的基本框架,分的過於細緻了(畢竟是標準),為了便於我們理解和記憶,我們將其按 tcp/ip 五層模型的方式進行講解
如圖所示,我們把最底下的一層稱為“物理層“,最上面的一層叫做"應用層",中間的三層(自上而下)分別為"傳輸層"、“網路層“、”資料鏈路層“。
越上面的層,越靠近使用者。越下面的層,越接近硬體。
五層模型
之所以把網際網路進行分層,一方面是由於歷史原因:因特網一開始的設計初衷是為了美國國防部應對蘇聯的核戰爭,後來的一些網路協議則是基於因特網之上層層疊加,另一方面網路協議太過複雜:將其按分層思想拆解有助於標準化
記住每一層都是為了實現一種功能,為了實現這個功能,大家必須遵守共通的規則,我們稱之為“協議”,下面我們介紹每一層的職責
物理層
假設給你兩臺電腦,希望它們進行互動,第一件事應該幹什麼?
當然是要進行組網,那麼務必要通過光纖和電纜或者無線電波等等方式讓兩臺電腦能夠傳輸訊號
這就叫做”物理層“,它確保原始的資料可在各種物理媒體上傳輸,作用:負責提供資料傳輸的物理支援
如:寬頻接入,提供資料通訊系統,傳輸媒體等
雖然寥寥數語總結了物理層的功能,可實際上物理層比我們想象的複雜的多。
但是我們只要記住它最終主要目的:傳輸0和1的電訊號
鏈路層
鏈路層的主要目的:
- 誤差糾正控制:在原始的、有差錯的物理傳輸線路的基礎上,採取差錯檢測、差錯控制與流量控制等方法,將有差錯的物理線路改進成邏輯上無差錯的資料鏈路。即 保障訊號無差錯傳輸。
- 幀編碼:定義一個包含資訊頻率、位同步、源地址、目標地址以及其他控制資訊的資料包。即 0和1的電訊號變成資料包
簡而言之:
這就是鏈路層的功能,它在物理層的上方,定義了單個鏈路上如何傳輸資料
如何將資料組合成資料塊?如何控制其在物理通道上傳輸?如何無差錯傳輸?
乙太網協議
乙太網是目前最流行的一種區域網組網技術,乙太網協議規定傳送資料必須按一定的格式,並將此資料格式稱為“幀”
每一幀真正意義上包含5個欄位(瞭解即可)
- 目的地址(DA域):接收節點的地址
- 源地址(SA域):傳送節點的地址
- 長度和型別:2位元組長度<=1518,代表資料欄位的長度,若大於,則表示該乙太網幀中的資料屬於哪個上層協議(例如0x800,代表IP資料包;0x806,代表ARP資料包等)
- 資料和填充:上層遞交的要傳送的實際資料
- CRC:資料包校驗碼
邏輯上看的話其實就是兩個部分,前半部分可以看作是資料頭,包含傳送者(源地址),接收者(目標地址),長度和型別;後半部分可以看作是要傳輸的資料
當有需要傳送的資料時,資料鏈路層會將遞交來的資料按某種格式再加上一定的控制資訊,然後再由物理層傳送出去。
資料鏈路層交給物理層的資料格式就被稱為 “乙太網幀格式”
MAC地址
上文提到,乙太網幀格式中,包含了傳送方和接收方的節點地址。那麼這個地址到底是什麼呢?
每一臺電腦需要聯網,那麼出廠時,各大廠商一定會給其安裝一個名為“網路卡”的裝置。每一塊網路卡都有一個MAC地址,在網路通訊中它可以看作機器的唯一固定識別標識。
資料包會從一塊網路卡,傳送到另一塊網路卡
廣播
然後我們再想想,在傳送的時候,傳送方的網路卡怎麼能知道接收方網路卡的MAC地址?
答:有一種協議,叫做ARP(Address Resolution Protocol)協議,“地址解析協議”,在網路層我們再詳細解剖ARP協議步驟
現在我們已經能夠通過ARP協議拿到目標的MAC地址了,系統怎麼能將資料包準確的傳送給對方呢?
答:乙太網採用了一種很"原始"的方式,它不是把資料包準確送到接收方,而是向本網路內所有計算機傳送,讓每臺計算機自己判斷,是否為接收方。
上圖中,1號計算機向2號計算機傳送一個資料包,同一個子網路的3號、4號、5號計算機都會收到這個包。它們讀取這個包的"標頭",找到接收方的MAC地址,然後與自身的MAC地址相比較,如果兩者相同,就接受這個包,做進一步處理,否則就丟棄這個包。這種傳送方式就叫做"廣播"(broadcasting)。
有了資料包的定義、網路卡的MAC地址、廣播的傳送方式,"鏈路層"就可以在多臺計算機之間傳送資料了。
網路層
乙太網協議,依靠MAC地址傳送給指定目標資料。雖然,只知道MAC地址,北京的網路卡也可以找到紐約的網路卡,技術上也確實可以做到。但是有重大的效能缺陷。
試想一下,如果全世界的裝置都使用MAC地址相連,那麼網橋在習得之前就得向全世界傳送資料包,可想而知那將會造成多大的網路流量。而且由於沒有任何集約機制,網橋就不得不維護一個巨大的表格來維護學到的所有MAC地址。一旦這些資訊超過網橋所能承受範圍的極限,那將導致網橋無法正常工作,也就無法實現正常通訊的。簡而言之,雖然單單隻依靠MAC地址也能找到要傳送的目標,但是無異於大海撈針,效率低下,全世界都這麼做會導致通訊系統崩潰。
網際網路是由無數個子網而組成的一個巨型網路,很難想象北京和紐約的電腦會處於同一個子網,這幾乎是不可能的。
因此,必須找到一種方法,能夠區分哪些MAC地址屬於同一個子網路,哪些不是。如果是同一個子網路,就採用廣播方式傳送,否則就採用"路由"方式傳送。("路由"的意思,就是指如何向不同的子網路分發資料包,這是一個很大的主題,本文不涉及。)
這就導致了"網路層"的誕生。它的作用是引進一套新的地址,使得我們能夠區分不同的計算機是否屬於同一個子網路。這套地址就叫做"IP"地址。
於是“網路層”出現以後,每臺計算機有了兩種地址,一種是MAC地址,另一種是IP地址,兩種地址沒有任何聯絡,MAC地址是由網路卡決定,IP地址也可以動態分配,它們隨機組合
"IP"地址用於幫助我們確認目標所在的子網路,MAC地址則將資料包送到該子網路的目標網路卡。因此一定是先處理IP地址,再處理MAC地址,才能找到目標。
IP協議
“IP”地址,是由IP協議所規定的,目前採用較多的為 IPV4,由 32個二進位組成。
通常情況IP 地址的前一部分為網路號(net ID),後一部分為主機號(host ID)
日常工作中,我們習慣使用四段的十進位制位來表示IP地址, 從0.0.0.0一直到255.255.255.255
如果兩個電腦處於同一個子網路。那麼他們的IP地址的 網路號一定是相同的
比如,IP地址172.26.154.2,這是一個32位的地址,假定它的網路部分是前24位(172.26.154),那麼主機部分就是後8位(最後的那個2)
但是,問題在於單單從IP地址,我們無法判斷網路部分。還是以172.26.154.2為例,它的網路部分,到底是前24位,還是前16位,甚至前28位,從IP地址上是看不出來的。
那麼,怎樣才能從IP地址,判斷兩臺計算機是否屬於同一個子網路呢?這就要用到另一個引數"子網掩碼"(subnet mask)。
所謂"子網掩碼",就是表示子網路特徵的一個引數。它在形式上等同於IP地址,也是一個32位二進位制數字,它的網路部分全部為1,主機部分全部為0。比如,IP地址172.26.154.2,如果已知網路部分是前24位,主機部分是後8位,那麼子網路掩碼就是11111111.11111111.11111111.00000000,寫成十進位制就是255.255.255.0。
知道"子網掩碼",我們就能判斷,任意兩個IP地址是否處在同一個子網路。方法是將兩個IP地址與子網掩碼分別進行AND運算(兩個數位都為1,運算結果為1,否則為0),然後比較結果是否相同,如果是的話,就表明它們在同一個子網路中,否則就不是。
比如,已知IP地址172.26.154.2和172.26.154.233的子網掩碼都是255.255.255.0,請問它們是否在同一個子網路?兩者與子網掩碼分別進行AND運算,結果都是172.26.154.0,因此它們在同一個子網路。
總結一下,IP協議的作用主要有兩個,一個是為每一臺計算機分配IP地址,另一個是確定哪些地址在同一個子網路。
IP資料包
根據IP協議傳送的資料被稱為IP資料包。這其中包含IP地址資訊
但是我們之前有說過,乙太網的資料包只包含MAC地址和其相關資訊,並沒有IP地址的欄位。那麼是否需要修改資料定義呢,再新增一個欄位呢?
回答是不需要。我們可以把IP資料包直接放進乙太網資料包的"資料"部分,因此完全不用修改乙太網的規格。這就是網際網路分層結構的好處:上層的變動完全不涉及下層的結構。
具體來說 IP 資料包,也分為 “資料頭” 和 “資料” 兩部分
"標頭"部分主要包括版本、長度、IP地址等資訊,"資料"部分則是IP資料包的具體內容。它放進乙太網資料包後,乙太網資料包就變成了下面這樣。
IP資料包的"標頭"部分的長度為20到60位元組,整個資料包的總長度最大為65,535位元組。因此,理論上,一個IP資料包的"資料"部分,最長為65,515位元組。前面說過,乙太網資料包的"資料"部分,最長只有1500位元組。因此,如果IP資料包超過了1500位元組,它就需要分割成幾個乙太網資料包,分開傳送了。
ARP協議
關於網路層,還有一點需要說明
因為IP資料包是放在乙太網資料包裡進行傳輸的,所以我們必須同時知道兩個地址,一個是對方的MAC地址,一個是對方的IP地址。
而通常情況下我們傳送一個請求,會知道對方的域名+請求的URI 進行資料的傳輸,域名通過DNS伺服器會被解析程目標的IP地址,但是MAC地址呢,我們怎麼獲取MAC地址
所以這裡我們需要一個機制,通過IP地址獲取MAC地址
(其實這一步,筆者一直都認為是歷史原因,也許乙太網設計之初就沒想做一個全球性的大網,而伴隨著乙太網協議的普及,IP協議是依附於乙太網協議的之上,所以才需要這麼一步,IP地址攜帶主機號,理所應當可以定位唯一一臺機器了,獲取MAC地址純粹是因為IP協議是在乙太網協議之上,因此每每看ARP總有一種歷史遺留問題造成多次一舉的感覺)
ARP是如何通過IP獲取到目標的MAC地址呢?
假定主機A向同一鏈路上的主機B傳送IP包,主機A的地址為172.20.1.1,主機B的IP地址為172.20.1.2,它們互相不知道對方的MAC地址,主機A為了獲得主機B的MAC地址,起初要通過廣播傳送一個ARP請求包。這個包中包含了主機B的IP地址:172.20.1.2。由於廣播的包可以被同一個鏈路上所有的主機或路由器接收,因此ARP請求包也會被這同一個鏈路上所有的主機和路由器進行解析。如果ARP請求包中的目標IP地址與自己的IP地址一致,那麼這個節點就將自己的MAC地址塞入ARP響應包返回給主機A。
總之,從一個IP地址傳送ARP請求包可以瞭解其MAC地址,目標地址將自己的MAC地址填入其中的ARP響應包返回到IP地址
傳輸層
有了MAC地址和IP地址,我們已經可以在網路中進行自由通訊了。
但是,同一臺主機上會有很多的程式,我可以一邊登著QQ,一邊打LOL,還能聽酷狗。當一個資料包從網際網路的一臺機器傳輸到另一臺時,它如何確定的傳輸給一個指定的應用程式呢?
也就是說,我們還需要一個引數,用來確定這個資料包到底要給哪一個程式(程式)使用,這個引數就叫做“埠”(port)
埠是 0 到 65535之間的一個整數,正好16個二進位制位,0到1023的埠被系統佔用,使用者只能選用大於1023的埠。不管是瀏覽網頁還是線上聊天,應用程式會隨機選用一個埠,然後與伺服器的相應埠聯絡。
"傳輸層"的功能,就是建立"埠到埠"的通訊。相比之下,"網路層"的功能是建立"主機到主機"的通訊。只要確定主機和埠,我們就能實現程式之間的交流。因此,Unix系統就把主機+埠,叫做"套接字"(socket)。有了它,就可以進行網路應用程式開發了。
UDP協議
現在,我們又要在資料包中加入埠資訊,這就需要新的協議,最簡單的實現叫做UDP協議,UDP協議是面向資料包的協議,由於它的頭部會有length欄位標記整個資料包(UDP的首部+UDP資料)的總長度,故UDP協議是有訊息邊界的。
"標頭"部分主要定義了發出埠和接收埠,"資料"部分就是具體的內容。然後,把整個UDP資料包放入IP資料包的"資料"部分,而前面說過,IP資料包又是放在乙太網資料包之中的,所以整個乙太網資料包現在變成了下面這樣:
UDP資料包非常簡單,"標頭"部分一共只有8個位元組,總長度不超過65,535位元組,正好放進一個IP資料包。
UDP協議是不可靠的協議,傳輸過程中即使出現丟包,UDP也不負責重發,基本應用於:
- 視訊,音訊等多媒體通訊
- 包總量較少的通訊(DNS、SNMP等)
TCP協議
UDP協議的優點是比較簡單,容易實現,但是缺點是可靠性較差,一旦資料包發出,無法知道對方是否收到。
為了解決這個問題,提高網路可靠性,TCP協議就誕生了。這個協議非常複雜,但可以近似認為,它就是有確認機制的UDP協議,每發出一個資料包都要求確認。如果有一個資料包遺失,就收不到確認,發出方就知道有必要重發這個資料包了。
因此,TCP協議能夠確保資料不會遺失。它的缺點是過程複雜、實現困難、消耗較多的資源。
TCP是面向流的協議,它是沒有訊息邊界的,所以在通訊開發過程中,可能需要解決“黏包”、“拆包”的問題(面向流,其實就沒有包的概念,這麼說,主要想表達問題),其實根本問題還是資料在緩衝區進行傳輸的問題。
TCP資料流和UDP資料包一樣,都是內嵌在IP資料包的"資料"部分。TCP資料流沒有長度限制,理論上可以無限長,但是為了保證網路的效率,通常TCP資料流的長度不會超過IP資料包的長度,以確保單個TCP資料流不必再分割。
應用層
應用程式收到"傳輸層"的資料,接下來就要進行解讀。由於網際網路是開放架構,資料來源五花八門,必須事先規定好格式,否則根本無法解讀。
"應用層"的作用,就是規定應用程式的資料格式。
舉例來說,TCP協議可以為各種各樣的程式傳遞資料,比如Email、WWW、FTP等等。那麼,必須有不同協議規定電子郵件、網頁、FTP資料的格式,這些應用程式協議就構成了"應用層"。
HTTP協議
http協議是超文字傳輸協議,它是應用層協議,它定義了一個客戶端請求和Web伺服器應答的資料格式。
請求報文包含請求的方式、URL、協議版本、請求頭部和請求資料。伺服器以一個狀態行作為響應,響應的內容包括協議的版本、成功或者錯誤程式碼、伺服器資訊、響應頭部和響應資料。這些都是由http協議所要約束的。
這是最高的一層,直接面對使用者。它的資料就放在UDP資料包中的"資料"部分。因此,現在的乙太網的資料包就變成下面這樣。
至此我們按TCP/IP分層的五層模型就說完了,總體的流程圖如下: