ping 是基於 ICMP 協議工做的。ICMP全稱Internet Control Message Protocol,就是互聯網控制報文協議。
ICMP 報文是封裝在 IP 包裏面的。由於傳輸指令的時候,確定須要源地址和目標地址。它自己很是簡單。
ICMP 報文有不少的類型,不一樣的類型有不一樣的代碼。最經常使用的類型是主動請求爲 8,主動請求的應答爲 0。網絡
經常使用的ping 就是查詢報文,是一種主動請求,而且得到主動應答的 ICMP 協議。因此,ping 發的包也是符合 ICMP 協議格式的,只不過它在後面增長了本身的格式。
對 ping 的主動請求,進行網絡抓包,稱爲ICMP ECHO REQUEST。同理主動請求的回覆,稱爲ICMP ECHO REPLY。比起原生的 ICMP,這裏面多了兩個字段,一個是標識符(標識是請求仍是回覆),另外一個是序號(每一個發出的報文都有序號)。測試
在選項數據中,ping 還會存放發送請求的時間值,來計算往返時間,說明路程的長短。spa
終點不可達爲 3,源抑制爲 4,超時爲 11,重定向爲 5。
差錯報文的結構相對複雜一些。除了前面仍是 IP,ICMP 的前 8 字節不變,後面則跟上出錯的那個 IP 包的 IP 頭和 IP 正文的前 8 個字節。blog
ping 命令執行的時候,源主機首先會構建一個 ICMP 請求數據包,ICMP 數據包內包含多個字段。最重要的是兩個,第一個是類型字段,對於請求數據包而言該字段爲 8;另一個是順序號,主要用於區分連續 ping 的時候發出的多個數據包。每發出一個請求數據包,順序號會自動加 1。爲了可以計算往返時間 RTT,它會在報文的數據部分插入發送時間。路由
主機 B 會構建一個 ICMP 應答包,應答數據包的類型字段爲 0,順序號爲接收到的請求數據包中的順序號,而後再發送出去給主機 A。it
在規定的時候間內,源主機若是沒有接到 ICMP 的應答包,則說明目標主機不可達;若是接收到了 ICMP 應答包,則說明目標主機可達。此時,源主機會檢查,用當前時刻減去該數據包最初從源主機上發出的時刻,就是 ICMP 數據包的時間延遲。class
常常會遇到一個問題,若是不在咱們的控制範圍內,不少中間設備都是禁止 ping 的,可是ping 不通不表明網絡不通。這個時候就要使用 telnet,經過其餘協議來測試網絡是否通。route
ping 這個程序是使用了 ICMP 裏面的 ECHO REQUEST 和 ECHO REPLY 類型。路由器
有一個程序Traceroute,它會使用 ICMP 的規則,故意製造一些可以產生錯誤的場景。因此,Traceroute 的第一個做用就是故意設置特殊的 TTL,來追蹤去往目的地時沿途通過的路由器。互聯網
Traceroute 的參數指向某個目的 IP 地址,它會發送一個 UDP 的數據包。將TTL 設置成 1,也就是說一旦遇到一個路由器或者一個關卡,就表示它「犧牲」了。若是中間的路由器不止一個,固然碰到第一個就「犧牲」。因而,返回一個 ICMP 包,也就是網絡差錯包,類型是時間超時。
接下來,將 TTL 設置爲 2。第一關過了,第二關就「犧牲」了,那我就知道第二關有多遠。如此反覆,直到到達目的主機。這樣,Traceroute 就拿到了全部的路由器 IP。固然,有的路由器壓根不會回這個 ICMP。這也是 Traceroute 一個公網的地址,看不到中間路由的緣由。
怎麼知道 UDP 有沒有到達目的主機呢?Traceroute 程序會發送一份 UDP 數據報給目的主機,但它會選擇一個不可能的值做爲 UDP 端口號(大於 30000)。當該數據報到達時,將使目的主機的 UDP 模塊產生一份「端口不可達」錯誤 ICMP 報文。若是數據報沒有到達,則多是超時。
Traceroute 還有一個做用是故意設置不分片,從而肯定路徑的 MTU。要作的工做首先是發送分組,並設置「不分片」標誌。發送的第一個分組的長度正好與出口 MTU 相等。若是中間遇到窄的關口會被卡住,會發送 ICMP 網絡差錯包,類型爲「須要進行分片但設置了不分片位」。其實,這是人家故意的好吧,每次收到 ICMP「不能分片」差錯時就減少分組的長度,直到到達目標主機。
ping 使用查詢報文,Traceroute 使用差錯報文