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

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

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 章介紹埠號機制時一起講解。