1. 程式人生 > >網絡是怎樣連接的學習筆記-第二章-IP與以太網的包收發操作(四)

網絡是怎樣連接的學習筆記-第二章-IP與以太網的包收發操作(四)

出現 init 信號 height 這樣的 介質 操作系統 初始化 關於

2.5.9 向集線器發送網絡包

發送信號的半雙工和全雙工模式

加上報頭、起始幀分界符和 FCS 之後,我們就可以將包通過網線發送出去了。

發送信號的操作分為兩種,一種是使用集線器的半雙工模式,另一種是使用交換機的全雙工模式。

發送和接收同時並行的方式叫作“全雙工”,相對地,某一時刻只能進行發送或接收其中一種操作的叫作“半雙工”。

半雙工模式下的工作模式

在半雙工模式中,為了避免信號碰撞,首先要判斷網線中是否存在其他設備發送的信號。

如果有,則需要等待該信號傳輸完畢,因為如果在有信號時再發送一組信號,兩組信號就會發生碰撞。

當之前的信號傳輸完畢,或者本來就沒有信號在傳輸的情況下,我們就可以開始發送信號了。

MAC模塊將數字信息轉換為電信號

首先,MAC 模塊從報頭開始將數字信息按每個比特轉換成電信號,然後由 PHY,或者叫 MAU 的信號收發模塊發送出去。

將數字信息轉換為電信號的速率就是網絡的傳輸速率,例如每秒將 10 Mbit 的數字信息轉換為電信號發送出去,則速率就是 10 Mbit/s。

MAU和PHY的區別

根據以太網信號方式的不同,有些地方叫 MAU(Medium Attachment Unit,介質連接單元),有些地方叫 PHY(Physical Layer Device,物理層裝置)。在速率為 100 Mbit/s 以上的以太網中都叫 PHY。

PHY模塊將信號轉換為可在網線上傳輸的格式

接下來PHY(MAU)模塊會將信號轉換為可在網線上傳輸的格式,並通過網線發送出去。

以太網規格中對不同的網線類型和速率以及其對應的信號格式進行了規定,但 MAC 模塊並不關心這些區別,而是將可轉換為任意格式的通用信號發送給 PHY(MAU)模塊,然後 PHY(MAU)模塊再將其轉換為可在網線上傳輸的格式。

大家可以認為 PHY(MAU)模塊的功能就是對 MAC 模塊產生的信號進行格式轉換。

網線中實際傳輸的信號

當然,以太網還有很多不同的派生方式,網線傳輸的信號格式也有各種變化。

此外,實際在網線中傳輸的信號很復雜,我們無法一一介紹,但是如果一點都不講,大家可能對此難以形成一個概念,所以就舉一個例子,大家感受一下就好。

下圖就是一個例子,網線中實際傳輸的信號就是這個樣子的。

技術分享圖片

數據信號和時鐘信號疊加而成的信號,就是 10BASE-T 方式所使用的信號,這也是一個網線中實際傳輸的信號的例子。

PHY發送信號的同時還負責監控是否有信號進來

PHY在開始發送信號之前,需要先確認沒有其他信號進來,這時才能開始發送。

如果在信號開始發送到結束發送的這段時間內一直沒有其他信號進來,發送操作就成功完成了。

以太網不會確認信號是否被收到

以太網不會確認發送的信號對方有沒有收到。

根據以太網的規格,兩臺設備之間的網線不能超100米,在這個距離內極少會發生錯誤。

萬一發生錯誤,協議棧的 TCP 也會負責搞定,因此在發送信號時沒有必要檢查錯誤。

發生信號碰撞時所有發送操作停止

在發送信號的過程中,接收線路不應該有信號進來,但情況並不總是盡如人意,有很小的可能性出現多臺設備同時進行發送操作的情況。

如果有其他設備同時發送信號,這些信號就會通過接收線路傳進來。

在使用集線器的半雙工模式中,一旦發生這種情況,兩組信號就會相互疊加,無法彼此區分出來,這就是所謂的信號碰撞。

這種情況下發送操作會終止。為了通知其他設備當前線路已發生碰撞,還會發送一段時間的阻塞信號,然後所有的發送操作會全部停止。

阻塞信號

以太網中發生碰撞時,為了告知所有設備而發送的一種特殊信號。

等待時間根據MAC地址計算隨機生成

等待一段時間之後,網絡中的設備會嘗試重新發送信號。

但如果所有設備的等待時間都相同,那肯定還會發生碰撞,因此必須讓等待的時間相互錯開。

具體來說,等待時間是根據 MAC 地址生成一個隨機數計算出來的。

當網絡擁塞時,發生碰撞的可能性就會提高,重試發送的時候可能又會和另外一臺設備的發送操作沖突,這時會將等待時間延長一倍,然後再次重試。

以此類推,每次發生碰撞就將等待時間延長一倍,最多重試 10次,如果還是不行就報告通信錯誤。

雙全工模式不會發生信息碰撞

另一種全雙工模式我們會在第 3 章探索交換機時進行介紹,在全雙工模式中,發送和接收可以同時進行,不會發生碰撞。

因此,全雙工模式中不需要像半雙工模式這樣考慮這麽多復雜的問題,即便接收線路中有信號進來,也可以直接發送信號。

2.5.10 接收返回包

在使用集線器的半雙工模式以太網中,一臺設備發送的信號會到達連接在集線器上的所有設備。

這意味著無論是不是發給自己的信號都會通過接收線路傳進來,因此接收操作的第一步就這些信號全都收進來再說。

PHY模塊處理信號

PHY模塊將信號轉成通用格式發送給MAC模塊。

MAC模塊處理信號

開始轉換數字信息

信號的開頭是報頭,通過報頭的波形同步時鐘,然後遇到起始幀分界符時開始將後面的信號轉換成數字信息。

檢查FCS幀校驗序列

當到達信號的末尾時,還需要檢查 FCS。

具體來說,就是將從包開頭到結尾的所有比特套用到公式中計算出 FCS,然後和包末尾的 FCS 進行對比。

正常情況下兩者應該是一致的,如果中途受到噪聲幹擾而導致波形發生紊亂,則兩者的值會產生差異,這時這個包就會被當作錯誤包而被丟棄。

比對MAC地址

如果 FCS 校驗沒有問題,接下來就要看一下 MAC 頭部中接收方MAC 地址與網卡在初始化時分配給自己的 MAC 地址是否一致,以判斷這個包是不是發給自己的。

我們沒必要去接收發給別人的包,因此如果不是自己的包就直接丟棄,如果接收方 MAC 地址和自己 MAC 地址一致,則將包放入緩沖區中。

網卡通知計算機

到這裏,MAC 模塊的工作就完成了,接下來網卡會通知計算機收到了一個包。

通知計算機的操作會使用一個叫作中斷的機制。

在網卡執行接收包的操作的過程中,計算機並不是一直監控著網卡的活動,而是去繼續執行其他的任務。

如果網卡不通知計算機,計算機是不知道包已經收到了這件事的。

網卡驅動也是在計算機中運行的一個程序,因此它也不知道包到達的狀態。

在這種情況下,我們需要一種機制能夠打斷計算機正在執行的任務,讓計算機註意到網卡中發生的事情,這種機制就是中斷。

中斷機制

具體來說,中斷的工作過程是這樣的。

首先,網卡向擴展總線中的中斷信號線發送信號,該信號線通過計算機中的中斷控制器連接到 CPU。

當產生中斷信號時,CPU 會暫時掛起正在處理的任務,切換到操作系統中的中斷處理程序。

然後,中斷處理程序會調用網卡驅動,控制網卡執行相應的接收操作。

中斷是有編號的,網卡在安裝的時候就在硬件中設置了中斷號,在中斷處理程序中則將硬件的中斷號和相應的驅動程序綁定。

例如,假設網卡的中斷號為 11,則在中斷處理程序中將中斷號 11 和相應的網卡驅動綁定起來,當網卡發起中斷時,就會自動調用網卡驅動了。

現在的硬件設備都遵循即插即用規範自動設置中斷號,我們沒必要去關心中斷號了,在以前需要手動設置中斷號的年代,經常發生因為設置了錯誤的中斷號而導致網卡無法正常工作的問題。

判斷協議類型把包交給對應的協議棧

網卡驅動被中斷處理程序調用後,會從網卡的緩沖區中取出收到的包,並通過 MAC 頭部中的以太類型字段判斷協議的類型。

現在我們在大多數情況下都是使用 TCP/IP 協議,但除了 TCP/IP 之外還有很多其他類型的協議,例如 NetWare 中使用的 IPX/SPX,以及 Mac 電腦中使用的 AppleTalk等協議。

這些協議都被分配了不同的以太類型,如 0080(十六進制)代表IP 協議,網卡驅動就會把這樣的包交給 TCP/IP 協議棧。

如果是 809B 則表示 AppleTalk 協議,就把包交給 AppleTalk 協議棧,以此類推。

前提是操作系統內部存在以太類型所對應的協議棧。

如果不存在相應的協議棧,則會視作錯誤,直接丟棄這個包。

協議棧判斷將這個包交給那個應用程序

按照探索之旅的思路,大家可能會認為向 Web 服務器發送包之後,後面收到的一定是 Web 服務器返回的包,其實並非如此。

計算機中同時運行了很多程序,也會同時進行很多通信操作,因此收到的包也有可能是其他應用程序的。

不過,即便如此也沒問題,網卡不會關心包裏的內容,只要按照以太類型將包交給對應的協議棧就可以了。

接下來,協議棧會判斷這個包應該交給哪個應用程序,並進行相應的處理。

2.5.11 將服務器的響應包從 IP 傳遞給 TCP

IP模塊處理接收的包

假設 Web 服務器返回了一個網絡包,服務器返回的包的以太類型應該是 0800,因此網卡驅動會將其交給 TCP/IP 協議棧來進行處理。

檢查IP頭部的格式

接下來就輪到 IP 模塊先開始工作了,第一步是檢查 IP 頭部,確認格式是否正確。

檢查IP地址

如果格式沒有問題,下一步就是查看接收方 IP 地址。

如果接收網絡包的設備是一臺 Windows 客戶端計算機,那麽服務器返回的包的接收方 IP 地址應該與客戶端網卡的地址一致,檢查確認之後我們就可以接收這個包了。

如果接收方 IP 地址不是自己的地址,那一定是發生了什麽錯誤。客戶端計算機不負責對包進行轉發,因此不應該收到不是發給自己的包。

如果是服務器就不一定了,服務器可以像路由器一樣對包進行轉發。

通過ICMP消息將錯誤告知發送方

當發生這樣的錯誤時,IP 模塊會通過 ICMP 消息將錯誤告知發送方(圖 2.1)。

ICMP 規定了各種類型的消息,如表 2.4 所示。

當我們遇到這個錯誤時,IP模塊會通過表 2.4 中的 Destination unreachable 消息通知對方。

技術分享圖片

檢查完畢後還原網絡包

如果接收方 IP 地址正確,則這個包會被接收下來,這時還需要完成另一項工作。

IP 協議有一個叫作分片的功能,具體的內容我們將在第 3 章探索路由器時進行介紹。

簡單來說,網線和局域網中只能傳輸小包,因此需要將大的包切分成多個小包。

如果接收到的包是經過分片的,那麽 IP 模塊會將它們還原成原始的包。

保存分片的包的ID

分片的包會在 IP 頭部的標誌字段中進行標記,當收到分片的包時,IP 模塊會將其暫存在內部的內存空間中,然後等待 IP頭部中具有相同 ID 的包全部到達,這是因為同一個包的所有分片都具有相同的 ID。

對包進行分片重組

此外,IP 頭部還有一個分片偏移量(fragment offset)字段,它表示當前分片在整個包中所處的位置。根據這些信息,在所有分片全部收到之後,就可以將它們還原成原始的包,這個操作叫作分片重組。

TCP模塊處理接受的包

TCP模塊根據IP和端口查找對應的套接字

到這裏,IP 模塊的工作就結束了,接下來包會被交給 TCP 模塊。

TCP模塊會根據 IP 頭部中的接收方和發送方 IP 地址,以及 TCP 頭部中的接收方和發送方端口號來查找對應的套接字。

找到對應的套接字之後,就可以根據套接字中記錄的通信狀態,執行相應的操作了。

如果包的內容是應用程序數據,則返回確認接收的包,並將數據放入緩沖區,等待應用程序來讀取

如果是建立或斷開連接的控制包,則返回相應的響應控制包,並告知應用程序建立和斷開連接的操作狀態。

TCP模塊需要獲取IP模塊中的IP地址

當包交給 TCP 模塊之後,TCP 模塊需要查詢 IP 頭部中的接收方和發送方 IP 地址來查找相應的套接字。

但是嚴格來說,TCP 模塊和 IP 模塊有各自的責任範圍,TCP 頭部屬於 TCP 的責任範圍,而 IP 頭部屬於 IP 模塊的責任範圍。TCP 模塊去查詢它等於是越權了。

如果根據這種嚴格的劃分來開發程序的話,IP 模塊和 TCP 模塊之間的交互過程必然會產生成本。

而且 IP模塊和 TCP 模塊進行類似交互的場景其實非常多,總體的交互成本就會很高,程序的運行效率就會下降。

不妨將責任範圍劃分得寬松一些,將 TCP 和 IP 作為一個整體來看待,這樣可以帶來更大的靈活性。

此外,關於為什麽查找套接字同時需要接收方和發送方的 IP 地址和端口號,我們會在第 6 章介紹端口號機制時一起講解。

網絡是怎樣連接的學習筆記-第二章-IP與以太網的包收發操作(四)