目錄
1.網絡協議
(1)網絡的起源
(2)為什么需要協議
(3)協議分層及其設計的解耦
(4)OSI定義的七層網絡模型
①分層及其功能
②TCP/IP協議
③傳輸層協議(TCP和UDP)
2.網絡通信
(1)IP、MAC地址
①MAC地址
②IP地址
③通信中MAC地址和IP地址的區別
(2)通信過程
①封裝和解包
②IP和MAC在通信過程中的作用
③端口號
④路由和路由器
(3)通信過程中的解耦合設計
①端口號和PID
②網卡發送
(4)網絡字節序
(5)以太網和令牌環網的概念
1.網絡協議
(1)網絡的起源
起初,計算機在一個小范圍內通信,即在局域網內通信。但是隨著發展計算機有著更大的通信需求,需要通過服務器進行數據共享,于是出現了廣域網。總體劃分,網絡主要分為廣域網和局域網(城域網等是后來細化發展出來的)。
人們有通信的需求,相應的,計算機也一定會產生通信的需求。計算機為人服務,而通信就是人很大的需求,因此網絡的誕生是必然而不是偶然。
(2)為什么需要協議
不同計算機有著共同的底層,即0和1表示數據,但不同計算機表示0和1的方式不一致(如光電信號的強弱,電信號的有無等),系統的設計也不一樣。要讓不同底層、系統實現計算機通信,我們要如何抹平硬件的設計差異呢?這就需要若干軟件層面的約定,即協議。協議的本質就是一套約定。兩臺計算機的通信需要約定,就像我們打電話接通后的第一聲“喂”就是人們公認的表示接通電話的約定。
實際上,在系統里面,CPU和內存、磁盤之間也存在自己的協議,包括計算機內的硬件、嵌入式設備都有自己的協議,這樣才能實現硬件通信。總的來說,協議無處不在,網絡協議只是其中一個部分(國際協會做的公認的標準之一)。
在網絡中,我們希望主機A、C能夠通信,但和系統內的進程間通信不同,網絡通信的物理距離變長了,通信的特征變化了會帶來新的問題,主機A怎么發到路由器呢?怎么找到主機B呢?數據丟失怎么辦呢?B怎么知道我的數據應該怎么處理呢?這就需要新的協議。
HTTP、FTP、SSH等都是廣為使用的應用層協議
(3)協議分層及其設計的解耦
要實現通信,需要經過多個軟件協議,這些協議是分層的,可以說它們相互是解耦合的。協議分層在設計上更模塊化,更好維護。在C++中,繼承和多態體系下的類的設計就是分層的,父子分層,可以更好維護層狀體系。
假設現在有兩個用戶通信,用戶之間遵循的協議是語言層,而通信設備之間遵循的協議是設備通信層。在用戶看來,他們是通過語言來通信的,他們也能聽懂彼此的話。這反映出通信也是分層的,用戶一直認為是在語言層通信,對設備來說一直都在設備通信層通信。平層的協議當然能夠互相理解。簡單來說,一層協議就是一個結構體,發送端發送該層的一個結構體,接收端當然知道如何處理,因為寫這個結構體的人早考慮好了。
同樣的,我們可以以分層的視角來看待系統了,它也是各層之間解耦合的,并且進程間通信也是各層之間互相通信實現的。在編程語言中,類與類之間也是分層的,分層后可以通過不同層之間的接口來調用,這樣出問題后可以很快排查、定位問題。
(4)OSI定義的七層網絡模型
①分層及其功能
雖然有七層,但定標準和實現的是不同人。OSI規定了標準,要求其它公司寫系統需要遵循該網絡協議,這些公司實現時發現不需要這么復雜,就省去了,但必要的接口都是按照標準來的,因此OSI還是實現了它的目標。
下面是常見的協議分層(5層)
應用層和傳輸層還存在表示層和會話層,后續用到再說,大部分情況這5層就足夠了。
②TCP/IP協議
雖然說不同層有不同協議,但TCP和IP是這個網絡協議棧的核心,于是OSI定義的這個網絡協議就可將其稱為TCP/IP協議。
③傳輸層協議(TCP和UDP)
傳輸層常見的協議有TCP和UDP。
TCP的性質是面向連接、可靠傳輸、面向字節流。
UDP的性質是不面向連接、不可靠傳輸、面向數據報。
簡單來說,TCP可用于轉賬、下單等與數據可信度要求高的應用,而UDP用于直播等對小型丟包感知不強的應用。
TCP面向字節流,意思是把數據緩存起來后由用戶自己決定如何取出數據,可以一次性讀出來,也可以多讀幾次。而UDP的面向數據報就像寄快遞,發的時候就決定了接收數據時一定要全拿走。
2.網絡通信
(1)IP、MAC地址
①MAC地址
MAC地址是48bit,共6字節,用16進制 + 冒號表示(如08:00:27:03:89:19)。
Windows在cmd里面用ipconfig /all查看,MAC在出廠時就確定了,在Windows里,可能切換網絡后MAC會變化。
MAC地址具有唯一性,原則上說MAC地址可以是任何值,只需要在局域網內不沖突就可以了。
MAC地址是在一個局域網里面標識自己的地址。有了MAC地址,就能實現局域網通信。形象來說,老師在班上教訓某個同學,在班上的其他同學都能聽到內容,但他們不需要做任何處理,這個MAC就是同學的名字。同一局域網內所有主機都能收到消息,只不過MAC不匹配會丟棄消息。一個班上不能出現同名的人,對應MAC地址在局域網內的唯一性。但在不同班里可能有同名的人。
②IP地址
IP地址有IPv4和IPv6,現在IPv6還未完全普及開,所以后續的IP地址默認都是指的IPv4。IPv4是4字節、32bit的數據。.用來隔開4個0-255的數字。
如192.168.34.45是字符串風格的IP地址,點分十進制提高了可讀性。網絡中常用char.char.char.char四字節表示IP(如struct IP里面的成員變量有char p1、p2、p3、p4),這兩種表示可以互相轉換。
在Linux的eth0可查看自己的IP地址
從局域網通信 -> 跨子網通信,不同實驗室實現了不同局域網通信方式。IP的出現使得不同的主機可以相互通信,就算局域網不同,但它們IP之上完全一樣,IP是對底層網絡屏蔽差異化的解決方案。
③通信中MAC地址和IP地址的區別
在網絡通信中,通信的源和目的IP地址是永遠不變的,MAC地址在經過一個地方后就會變化。類似于旅行,始終存在兩條路線,其中長期路線永遠不變(對應源IP和目的IP);同時,也有當前的位置和即將前往的目的地,這個一直在變(源MAC地址和目的MAC地址)。
(2)通信過程
①封裝和解包
應用層要相互通信,就要先把數據傳到物理層(網卡)。經過每層的通信時,數據前面會多封裝一個協議報頭,類似于快遞單和快遞盒子 + 數據,每經過一層協議,就會套一層包裝。
應用層報頭、傳輸層報頭、網絡層報頭、數據鏈路層報頭。物理層的主要功能是發送數據,它沒有嚴格意義上的報頭。報文 = 報頭 + 有效載荷,每一層的報文向下傳遞后其整體又被作為有效載荷處理。
網絡層報頭包含源IP和目的IP,數據鏈路層包含當前設備的MAC和下一個設備的MAC
物理層將數據發送后,網卡收到數據后會觸發硬件中斷,讓系統來處理,接收方會像棧一樣,一層一層分析報頭,一層層解包,去掉該層的報頭得到的就是有效載荷。當前層的報頭內部必須包含一個字段,記錄接下來要將自己的有效載荷交給誰,就像鏈表的指針一樣。
簡單來說,每一層得到自己的報文后,都能看懂報頭的內容,也知道有效載荷應該交給誰。這些都基于同層協議之間的數據能夠理解的基礎上,就像人和人的溝通,同層之間肯定沒有障礙。
②IP和MAC在通信過程中的作用
在封裝過程中,網絡層會封裝IP(源IP和目的IP),數據鏈路層會封裝MAC幀(源MAC地址和目的MAC地址)。
在通信過程中,主機A可能會經過路由器B(路由指的就是路徑選擇)才能交到C中。主機A封裝時會把目的MAC設置成B的MAC,因此當數據傳給B時,B解到數據鏈路層時發現跟自己的MAC匹配,再解包到網絡層。
解包到網絡層后就得到了源IP和目的IP,之后路由器會根據源IP和目的IP進行路由,再向下封裝,重新封裝MAC地址(設置下一個源MAC和目的MAC),繼續通過MAC交給另一個子網。如此往復,直到達到目的地址。
整個通信過程中,MAC地址一直在解包和封裝,而網絡層的IP地址不會變,MAC地址就像脫衣服穿衣服一樣,一直根據當前的設備在變化。就像旅游一樣,從重慶到海南是源IP和目的IP,而旅行途中要先從貴州開到廣西則是源MAC和目的MAC,它們會隨著當前位置的改變而改變。
整個過程我們要記住路由器之間的解包是解到網絡層停止,不會向上交付,因為目的IP不匹配。
在局域網內,其它主機也會收到消息,但當它們解包到數據鏈路層時,發現目標MAC不是自己,于是就會直接丟掉數據,應用層根本感知不到自己收到過數據。這就是前面提及的教室里面老師和學生通信時其他同學的處理方式。
③端口號
目的IP在網絡中標識主機的唯一性。但在整個通信過程中僅有IP是不夠的,因為數據借助IP傳輸到主機只是手段,數據到達主機內部,再交給主機內的進程才是目的。因此,網絡通信的本質就是進程間通信IPC。
數據在網絡層向上交付給進程需要端口號(port),這是傳輸層的內容,端口號共2字節16bit(十進制對應0 - 65535),每一個端口號和進程關聯,告訴系統這個數據要交給哪個進程來處理。總的來說,IP + 端口號(socket)合起來才標志某一臺主機的某一個具體的進程。兩個進程通過網絡這個公共資源來進行socket通信。
對于端口號的分配來說,0-1023一般被固定了,1023-65535是OS動態分配的端口號,也是客戶端程序的端口號
對于服務端和客戶端來講,如果要通信,IP和端口號都是必不可少的,一般來說手機里面下載的軟件里面就保存了要訪問的服務器的IP和端口號,第一次建立通信時客戶端也要發送自己的IP和端口號,這樣服務端才知道如何返回響應。
④路由和路由器
兩個不同子網通信必須要經過路由器。根據前面的通信過程我們也能發現,路由器是工作在網絡層的,路由器在兩端主機看來都各自認為路由器在自己的局域網內,實際上,子網是路由器構建的,子網內主機的IP地址都是路由器給的,首次連接后主機也能知道路由器的MAC、IP地址。路由器硬件內部有以太網和令牌環的驅動程序,可以和不同子網通信。同時路由器自己也有IP地址,并且能夠進行判斷目的IP是不是在同一局域網(同一子網內主機的IP地址基本是一致的),并可以選擇下一步轉發數據給誰,這個路徑的選擇過程就叫路由。
(3)通信過程中的解耦合設計
①端口號和PID
為什么要有端口號而不直接用pid?pid是進程管理的范疇,如果網絡使用pid,那么網絡和進程管理就耦合了。如果系統修改pid,網絡管理也要跟著改,這顯然不合理。
引入端口號之后,只需要一個軟件層(如哈希表)即可實現pid和端口號的轉變。一般來說,系統會維護一個65535個元素的哈希表,下標就是端口號。系統將進程PCB的地址存到表中,當接收到端口號時,直接根據報文查哈希表就能找到PCB,進而通信。
②網卡發送
最后利用網卡發送消息,實際上不需要在系統上大動干戈,只需要將file底層指向的方法改成網卡發送的方法,這樣系統直接對文件操作,是可以實現對網絡進行操作。這就是系統管理和網絡管理的解耦合,加入新功能毫不影響原來系統的設計。
有了系統和網絡的解耦合,進程間通信可以替換成網絡通信,即網絡通信實現本地通信,只需用網絡的一套規則,將發送方和接收方都設置成自己即可。
(4)網絡字節序
小端:低權值放低地址,高權值放高地址
大端:低權值放高地址,高權值放低地址
網絡規定所有發送到網絡上的數據必須都是大端的,對于數據0x11223344,采用大端按照從低地址到高地址發送數據,就會先發送1(高權值),一般來說這里就是報頭的位置,因此這種處理易于邊讀邊分析。
OS可能采用不同字節序,但這沒有關系,OS根據自己的設計轉換即可。
(5)以太網和令牌環網的概念
以太網,名字來源于物理學的以太,這算是物理概念的遷移。
令牌環就是誰有令牌環就只能誰說話,令牌就是上鎖。
在以太網中同一時間只能存在一份有效報文,這樣才能盡量避免光電信號干擾。如果有多個用戶之間要通信,就會進行數據的碰撞檢測,一般來說系統為了避免碰撞,會選擇等一會重發。這個以太網難道不就類似系統中的臨界資源嗎?碰撞避免難道不就類似加鎖嗎?并且整個以太網也是一個生產消費模型。
因此一個局域網也是一個碰撞域,主機越少,碰撞的概率就越低;主機越多,網絡就可能更差,因為碰撞避免多了,主機休眠時間長了。