BACK
Featured image of post 每天都在用的 Ping 命令,它到底是什麼?

每天都在用的 Ping 命令,它到底是什麼?

Ping命令很簡單,但作為為數不多的網絡檢測工具,卻非常有用,是開發網絡應用時最常用到的命令。雖然Ping這個動作這麼簡單,但你知道Ping命令背後後的邏輯嗎?跟著本篇文章瞭解一下!

參考網站
參考網站
參考網站


前言

老於網絡編程熟手來說,在測試和部署網絡通信應用(比如IM聊天、實時音視頻等)時,如果發現網絡連接超時,第一時間想到的就是使用Ping命令,Ping一下服務器看看通不通。甚至在有些情況下通過圖形化的Ping命令工具對目標網絡進行長測(比如:《兩款增強型Ping工具:持續統計、圖形化展式網絡狀況[附件下載]》、《網絡測試:Android版多路ping命令工具EnterprisePing[附件下載]》),可以得出當前網絡通信的網絡延遲網絡丟包率網絡抖動等等有價值信息。

Ping命令很簡單,但作為為數不多的網絡檢測工具,卻非常有用,是開發網絡應用時最常用到的命令。雖然Ping這個動作這麼簡單,但你知道Ping命令背後後的邏輯嗎?跟著本篇文章瞭解一下!


Ping命令的作用和原理

簡單來說,「ping」是用來探測本機與網絡中另一主機之間是否可達的命令,如果兩台主機之間ping不通,則表明這兩台主機不能建立起連接。ping是定位網絡通不通的一個重要手段。

ping 命令是基於 ICMP 協議來工作的,「ICMP」全稱為Internet 控制報文協議(Internet Control Message Protocol)。ping 命令會發送一份ICMP回顯請求報文給目標主機,並等待目標主機返回ICMP回顯應答。因為ICMP協議會要求目標主機在收到消息之後,必須返回ICMP應答消息給源主機,如果源主機在一定時間內收到了目標主機的應答,則表明兩台主機之間網絡是可達的。

舉一個例子來描述「ping」命令的工作過程:

  1. 假設有兩個主機,主機A(192.168.0.1)和主機B(192.168.0.2),現在我們要監測主機A和主機B之間網絡是否可達,那麼我們在主機A上輸入命令:
1
ping 192.168.0.2。
  1. 此時,ping 命令會在主機A上構建一個ICMP請求數據包(數據包裡的內容後面再詳述),然後ICMP協議會將這個數據包以及目標IP(192.168.0.2)等信息一同交給IP層協議。

  2. IP層協議得到這些信息後,將源地址(即本機IP)、目標地址(即目標IP:192.168.0.2)、再加上一些其它的控制信息,構建成一個IP數據包

  3. IP數據包構建完成後,還不夠,還需要加上MAC地址,因此,還需要通過ARP映射表找出目標IP所對應的MAC地址。當拿到了目標主機的MAC地址本機MAC後,一併交給數據鏈路層,組裝成一個數據幀,依據以太網的介質訪問規則,將它們傳送出出去。

  4. 當主機B收到這個數據幀之後,會首先檢查它的目標MAC地址是不是本機,如果是,就接收下來處理,接收之後會檢查這個數據幀,將數據幀中的IP數據包取出來,交給本機的IP層協議,然後IP層協議檢查完之後,再將ICMP數據包取出來交給ICMP協議處理,當這一步也處理完成之後,就會構建一個ICMP應答數據包,回發給主機A。

  5. 在一定的時間內,如果主機A收到了應答包,則說明它與主機B之間網絡可達;如果沒有收到,則說明網絡不可達。除了監測是否可達以外,還可以利用應答時間發起時間之間的差值,計算出數據包的延遲耗時

通過 ping 的流程可以發現,ICMP協議是這個過程的基礎,是非常重要的,下面的章節會把ICMP協議再詳細解釋一下,請繼續往下讀。


正確理解ICMP協議

Ping命令所基於的ICMP協議所處的網絡模型層級:

(▲ 上圖來自《計算機網絡通訊協議關係圖(中文珍藏版)[附件下載]》,您可下載此圖的完整清晰版)

Ping 命令這麼簡單,在任何系統上上手就能使用,很多人可能想當然的認為 Ping 命令使用的ICMP協議應該是基於傳輸層的TCP或UDP協議的吧?

正如上圖所示,ICMP協議不是基於TCP,也不是基於UDP,而是直接基於網絡層的IP協議,在整個網絡協議棧中屬於相當底層的協議了。這也從側面證明了它的重要性,因為根據ICMP的RFC手冊規定:ICMP協議是任何支持IP協議的系統必須實現的,沒有餘地。而IP協議是整個互聯網的基石,ICMP協議雖簡單,但重要性不言而喻。

所以,以後面試的時候,如果碰到"ICMP協議是基於什麼實現的?“這樣的問題,請一定要記往此節所講的內容。


深入ICMP協議

我們知道,ping 命令是基於ICMP協議來實現的。那麼我們再來看下圖,就明白了ICMP協議又是通過IP協議來發送的,即ICMP報文是封裝在IP包中(如下圖所示)。

IP協議是一種無連接的,不可靠的數據包協議,它並不能保證數據一定被送達,那麼我們要保證數據送到,就需要通過其它模塊來協助實現,這裡就引入的是ICMP協議

當傳送的IP數據包發送異常的時候,ICMP就會將異常信息封裝在包內,然後回傳給源主機。

將上圖再細拆一下可見:

繼續將ICMP協議模塊細拆:

由圖可知,ICMP數據包8bit的類型字段8bit的代碼字段以及16bit的校驗字段再加上選項數據組成。

ICMP協議大致可分為兩類:

  1. 查詢報文類型
  2. 差錯報文類型
ICMP報文類型類型的值ICMP的報文類型
差錯報文類型3終點不可達
4源點抑制
11時間超過
12參數問題
5改變路由
詢問報文8回送請求
0回送回答
13時間戳請求
14時間戳會帶
  • 【關於查詢報文類型】:

查詢報文主要應用於:ping 查詢子網掩碼查詢時間戳查詢等等。

上面講到的 ping 命令的流程其實就對應ICMP協議查詢報文類型的一種使用。在主機A構建ICMP請求數據包的時候,其ICMP的類型字段中使用的是8 (回送請求),當主機B構建ICMP應答包的時候,其ICMP類型字段就使用的是0 (回送應答),更多類型值參考上表。

對查詢報文類型的理解可參考一下文章最開始講的 ping 流程,這裡就不做贅述。

  • 【關於差錯報文類型】:

差錯報文主要產生於當數據傳送發送錯誤的時候。

它包括:目標不可達(網絡不可達、主機不可達、協議不可達、端口不可達、禁止分片等)、超時參數問題重定向(網絡重定向、主機重定向等)等等。

差錯報文通常包含了引起錯誤的IP數據包的第一個分片的IP首部,加上該分片數據部分的前8個字節。

當傳送IP數據包發生錯誤的時候(例如主機不可達),ICMP協議就會把錯誤信息封包,然後傳送回源主機,那麼源主機就知道該怎麼處理了。


ICMP差錯報文的妙用

正如上一節所介紹的那樣,ICMP協議主要有:查詢報文類型差錯報文類型兩種。對於差錯報文來說,是不是只有遇到錯誤的時候才能使用呢?不是

基於這個特性,Linux 下的 Traceroute 指令(Windows 下的對等指令是 tracert)利於ICMP的差錯報文可以實現遍歷到數據包傳輸路徑上的所有路由器!這真是個有用的命令!

百度百科上關於 traceroute 命令的用途:

traceroute (Windows 系統下是 tracert) 命令利用 ICMP 協議定位您的計算機和目標計算機之間的所有路由器。TTL 值可以反映數據包經過的路由器網關的數量,通過操縱獨立 ICMP 呼叫報文的 TTL 值和觀察該報文被拋棄的返回信息,traceroute 命令能夠遍歷到數據包傳輸路徑上的所有路由器

ICMP 的差錯報文的使用,使得 Traceroute 成為用來偵測源主機到目標主機之間所經過路由情況的常用工具。Traceroute 的原理就是利用ICMP的規則,製造一些錯誤的事件出來,然後根據錯誤的事件來評估網絡路由情況。

traceroute 的基本原理如下圖所示:

具體做法就是:

  1. Traceroute 會設置特殊的 TTL 值,來追踪源主機和目標主機之間的路由數。首先它給目標主機發送一個 TTL=1 的UDP數據包,那麼這個數據包一旦在路上遇到一個路由器,TTL 就變成了 0(TTL規則是每經過一個路由器都會減1),因為 TTL=0 了,所以路由器就會把這個數據包丟掉,然後產生一個錯誤類型(超時)的ICMP數據包回發給源主機,也就是差錯包。這個時候源主機就拿到了第一個路由節點的IP和相關信息了。

  2. 接著,源主機再給目標主機發一個 TTL=2 的UDP數據包,依舊上述流程走一遍,就知道第二個路由節點的IP和耗時情況等信息了。

  3. 如此反復進行,Traceroute 就可以拿到從主機A到主機B之間所有路由器的信息了。

但是有個問題是,如果數據包到達了目標主機的話,即使目標主機接收到 TTL 值為 1 的IP數據包,它也是不會丟棄該數據包的,也不會產生一份超時的ICMP回發數據包的,因為數據包已經達到了目的地嘛。那我們應該怎麼認定數據包是否達到了目標主機呢?

Traceroute 的方法是在源主機發送UDP數據包給目標主機的時候,會設置一個不可能達到的目標端口號(例如大於30000的端口號),那麼當這個數據包真的到達目標主機的時候,目標主機發現沒有對應的端口號,因此會產生一份端口不可達的錯誤ICMP報文返回給源主機。

可見 Traceroute 的原理確實很取巧,很有趣。如您對 Traceroute 感興趣,可以深入讀一讀《從 Traceroute 看網絡問題》一文。


comments powered by Disqus