聽說你 ping 用的很 6 ?給我圖解一下 ping 的工作原理!
每日一句英語學(xué)習(xí),每天進步一點點:
前言
在日常生活或工作中,我們在判斷與對方網(wǎng)絡(luò)是否暢通,使用的最多的莫過于 ping
命令了。
“那你知道 ping
是如何工作的嗎?” —— 來自小林的靈魂拷問
可能有的小伙伴奇怪的問:“我雖然不明白它的工作,但 ping 我也用的賊 6 ??!”
你用的是 6 ,但你能面試官面前,你就 6 不起來了,畢竟他們也愛問。
所以,我們要抱有「知其然,知其所以然」的態(tài)度,這樣就能避免面試過程中,出門右拐的情況了。
不知道的小伙伴也沒關(guān)系,今天我們就來搞定它,搞懂它。消除本次的問號,讓問號少一點。
正文
IP協(xié)議的助手 —— ICMP 協(xié)議
ping 是基于 ICMP
協(xié)議工作的,所以要明白 ping 的工作,首先我們先來熟悉 ICMP 協(xié)議。
ICMP 是什么?
ICMP 全稱是 Internet Control Message Protocol,也就是互聯(lián)網(wǎng)控制報文協(xié)議。
里面有個關(guān)鍵詞 —— 控制,如何控制的呢?
網(wǎng)絡(luò)包在復(fù)雜的網(wǎng)絡(luò)傳輸環(huán)境里,常常會遇到各種問題。當(dāng)遇到問題的時候,總不能死個不明不白,沒頭沒腦的作風(fēng)不是計算機網(wǎng)絡(luò)的風(fēng)格。所以需要傳出消息,報告遇到了什么問題,這樣才可以調(diào)整傳輸策略,以此來控制整個局面。
ICMP 功能都有啥?
ICMP
主要的功能包括:確認(rèn) IP 包是否成功送達目標(biāo)地址、報告發(fā)送過程中 IP 包被廢棄的原因和改善網(wǎng)絡(luò)設(shè)置等。
在 IP
通信中如果某個 IP
包因為某種原因未能達到目標(biāo)地址,那么這個具體的原因?qū)?strong style="font-size: inherit;line-height: inherit;color: rgb(48, 79, 254);">由 ICMP 負(fù)責(zé)通知。
如上圖例子,主機 A
向主機 B
發(fā)送了數(shù)據(jù)包,由于某種原因,途中的路由器 2
未能發(fā)現(xiàn)主機 B
的存在,這時,路由器 2
就會向主機 A
發(fā)送一個 ICMP
目標(biāo)不可達數(shù)據(jù)包,說明發(fā)往主機 B
的包未能成功。
ICMP 的這種通知消息會使用 IP
進行發(fā)送 。
因此,從路由器 2
返回的 ICMP 包會按照往常的路由控制先經(jīng)過路由器 1
再轉(zhuǎn)發(fā)給主機 A
。
收到該 ICMP 包的主機 A
則分解 ICMP 的首部和數(shù)據(jù)域以后得知具體發(fā)生問題的原因。
ICMP 包頭格式
ICMP 報文是封裝在 IP 包里面,它工作在網(wǎng)絡(luò)層,是 IP 協(xié)議的助手。
ICMP 包頭的類型字段,大致可以分為兩大類:
一類是用于診斷的查詢消息,也就是「查詢報文類型」
另一類是通知出錯原因的錯誤消息,也就是「差錯報文類型」
查詢報文類型
回送消息 —— 類型
0
和8
回送消息用于進行通信的主機或路由器之間,判斷所發(fā)送的數(shù)據(jù)包是否已經(jīng)成功到達對端的一種消息,ping
命令就是利用這個消息實現(xiàn)的。
可以向?qū)Χ酥鳈C發(fā)送回送請求的消息(ICMP Echo Request Message
,類型 8
),也可以接收對端主機發(fā)回來的回送應(yīng)答消息(ICMP Echo Reply Message
,類型 0
)。
相比原生的 ICMP,這里多了兩個字段:
標(biāo)識符:用以區(qū)分是哪個應(yīng)用程序發(fā) ICMP 包,比如用進程
PID
作為標(biāo)識符;序號:序列號從
0
開始,每發(fā)送一次新的回送請求就會加1
, 可以用來確認(rèn)網(wǎng)絡(luò)包是否有丟失。
在選項數(shù)據(jù)中,ping
還會存放發(fā)送請求的時間值,來計算往返時間,說明路程的長短。
差錯報文類型
接下來,說明幾個常用的 ICMP 差錯報文的例子:
目標(biāo)不可達消息 —— 類型 為
3
原點抑制消息 —— 類型
4
重定向消息 —— 類型
5
超時消息 —— 類型
11
目標(biāo)不可達消息(Destination Unreachable Message) —— 類型為
3
IP 路由器無法將 IP 數(shù)據(jù)包發(fā)送給目標(biāo)地址時,會給發(fā)送端主機返回一個目標(biāo)不可達的 ICMP 消息,并在這個消息中顯示不可達的具體原因,原因記錄在 ICMP 包頭的代碼字段。
由此,根據(jù) ICMP 不可達的具體消息,發(fā)送端主機也就可以了解此次發(fā)送不可達的具體原因。
舉例 6 種常見的目標(biāo)不可達類型的代碼:
網(wǎng)絡(luò)不可達代碼為
0
主機不可達代碼為
1
協(xié)議不可達代碼為
2
端口不可達代碼為
3
需要進行分片但設(shè)置了不分片位代碼為
4
為了給大家說清楚上面的目標(biāo)不可達的原因,小林犧牲自己給大家送 5 次外賣。
為什么要送外賣?別問,問就是為 35
歲的老林做準(zhǔn)備 …
a. 網(wǎng)絡(luò)不可達代碼為 0
外賣版本:
小林第一次送外賣時,小區(qū)里只有 A 和 B 區(qū)兩棟樓,但送餐地址寫的是 C 區(qū)樓,小林表示頭上很多問號,壓根就沒這個地方。
正常版本:
IP 地址是分為網(wǎng)絡(luò)號和主機號的,所以當(dāng)路由器中的路由器表匹配不到接收方 IP 的網(wǎng)絡(luò)號,就通過 ICMP 協(xié)議以網(wǎng)絡(luò)不可達(Network Unreachable
)的原因告知主機。
自從不再有網(wǎng)絡(luò)分類以后,網(wǎng)絡(luò)不可達也漸漸不再使用了。
b. 主機不可達代碼為 1
外賣版本:
小林第二次送外賣時,這次小區(qū)有 5 層樓高的 C 區(qū)樓了,找到地方了,但送餐地址寫的是 C 區(qū)樓 601 號房 ,說明找不到這個房間。
正常版本:
當(dāng)路由表中沒有該主機的信息,或者該主機沒有連接到網(wǎng)絡(luò),那么會通過 ICMP 協(xié)議以主機不可達(Host Unreachable
)的原因告知主機。
c. 協(xié)議不可達代碼為 2
外賣版本:
小林第三次送外賣時,這次小區(qū)有 C 區(qū)樓,也有 601 號房,找到地方了,也找到房間了,但是一開門人家是外國人說的是英語,我說的是中文!語言不通,外賣送達失敗~
正常版本:
當(dāng)主機使用 TCP 協(xié)議訪問對端主機時,能找到對端的主機了,可是對端主機的防火墻已經(jīng)禁止 TCP 協(xié)議訪問,那么會通過 ICMP 協(xié)議以協(xié)議不可達的原因告知主機。
d. 端口不可達代碼為 3
外賣版本:
小林第四次送外賣時,這次小區(qū)有 C 區(qū)樓,也有 601 號房,找到地方了,也找到房間了,房間里的人也是說中文的人了,但是人家說他要的不是外賣,而是快遞。。。
正常版本:
當(dāng)主機訪問對端主機 8080 端口時,這次能找到對端主機了,防火墻也沒有限制,可是發(fā)現(xiàn)對端主機沒有進程監(jiān)聽 8080 端口,那么會通過 ICMP 協(xié)議以端口不可達的原因告知主機。
e. 需要進行分片但設(shè)置了不分片位代碼為 4
外賣版本:
小林第五次送外賣時,這次是個吃播博主了 100 份外賣,但是吃播博主要求一次性要把全部外賣送達,小林的一臺電動車裝不下呀,這樣就沒辦法送達了。
正常版本:
發(fā)送端主機發(fā)送 IP 數(shù)據(jù)報時,將 IP 首部的分片禁止標(biāo)志位設(shè)置為1
。根據(jù)這個標(biāo)志位,途中的路由器遇到超過 MTU 大小的數(shù)據(jù)包時,不會進行分片,而是直接拋棄。
隨后,通過一個 ICMP 的不可達消息類型,代碼為 4 的報文,告知發(fā)送端主機。
原點抑制消息(ICMP Source Quench Message) —— 類型
4
在使用低速廣域線路的情況下,連接 WAN 的路由器可能會遇到網(wǎng)絡(luò)擁堵的問題。
ICMP
原點抑制消息的目的就是為了緩和這種擁堵情況。
當(dāng)路由器向低速線路發(fā)送數(shù)據(jù)時,其發(fā)送隊列的緩存變?yōu)榱愣鵁o法發(fā)送出去時,可以向 IP 包的源地址發(fā)送一個 ICMP 原點抑制消息。
收到這個消息的主機借此了解在整個線路的某一處發(fā)生了擁堵的情況,從而增大 IP 包的傳輸間隔,減少網(wǎng)絡(luò)擁堵的情況。
然而,由于這種 ICMP 可能會引起不公平的網(wǎng)絡(luò)通信,一般不被使用。
重定向消息(ICMP Redirect Message) —— 類型
5
如果路由器發(fā)現(xiàn)發(fā)送端主機使用了「不是最優(yōu)」的路徑發(fā)送數(shù)據(jù),那么它會返回一個 ICMP 重定向消息給這個主機。
在這個消息中包含了最合適的路由信息和源數(shù)據(jù)。這主要發(fā)生在路由器持有更好的路由信息的情況下。路由器會通過這樣的 ICMP 消息告知發(fā)送端,讓它下次發(fā)給另外一個路由器。
好比,小林本可以過條馬路就能到的地方,但小林不知道,所以繞了一圈才到,后面小林知道后,下次小林就不會那么傻再繞一圈了。
超時消息(ICMP Time Exceeded Message) —— 類型
11
IP 包中有一個字段叫做 TTL
(Time To Live
,生存周期),它的值隨著每經(jīng)過一次路由器就會減 1,直到減到 0 時該 IP 包會被丟棄。
此時,IP 路由器將會發(fā)送一個 ICMP 超時消息給發(fā)送端主機,并通知該包已被丟棄。
設(shè)置 IP 包生存周期的主要目的,是為了在路由控制遇到問題發(fā)生循環(huán)狀況時,避免 IP 包無休止地在網(wǎng)絡(luò)上被轉(zhuǎn)發(fā)。
此外,有時可以用 TTL 控制包的到達范圍,例如設(shè)置一個較小的 TTL 值。
ping —— 查詢報文類型的使用
接下來,我們重點來看 ping
的發(fā)送和接收過程。
同個子網(wǎng)下的主機 A 和 主機 B,主機 A 執(zhí)行ping
主機 B 后,我們來看看其間發(fā)送了什么?
ping 命令執(zhí)行的時候,源主機首先會構(gòu)建一個 ICMP 回送請求消息數(shù)據(jù)包。
ICMP 數(shù)據(jù)包內(nèi)包含多個字段,最重要的是兩個:
第一個是類型,對于回送請求消息而言該字段為
8
;另外一個是序號,主要用于區(qū)分連續(xù) ping 的時候發(fā)出的多個數(shù)據(jù)包。
每發(fā)出一個請求數(shù)據(jù)包,序號會自動加 1
。為了能夠計算往返時間 RTT
,它會在報文的數(shù)據(jù)部分插入發(fā)送時間。
然后,由 ICMP 協(xié)議將這個數(shù)據(jù)包連同地址 192.168.1.2 一起交給 IP 層。IP 層將以 192.168.1.2 作為目的地址,本機 IP 地址作為源地址,協(xié)議字段設(shè)置為 1
表示是 ICMP
協(xié)議,在加上一些其他控制信息,構(gòu)建一個 IP
數(shù)據(jù)包。
接下來,需要加入 MAC
頭。如果在本地 ARP 映射表中查找出 IP 地址 192.168.1.2 所對應(yīng)的 MAC 地址,則可以直接使用;如果沒有,則需要發(fā)送 ARP
協(xié)議查詢 MAC 地址,獲得 MAC 地址后,由數(shù)據(jù)鏈路層構(gòu)建一個數(shù)據(jù)幀,目的地址是 IP 層傳過來的 MAC 地址,源地址則是本機的 MAC 地址;還要附加上一些控制信息,依據(jù)以太網(wǎng)的介質(zhì)訪問規(guī)則,將它們傳送出去。
主機 B
收到這個數(shù)據(jù)幀后,先檢查它的目的 MAC 地址,并和本機的 MAC 地址對比,如符合,則接收,否則就丟棄。
接收后檢查該數(shù)據(jù)幀,將 IP 數(shù)據(jù)包從幀中提取出來,交給本機的 IP 層。同樣,IP 層檢查后,將有用的信息提取后交給 ICMP 協(xié)議。
主機 B
會構(gòu)建一個 ICMP 回送響應(yīng)消息數(shù)據(jù)包,回送響應(yīng)數(shù)據(jù)包的類型字段為 0
,序號為接收到的請求數(shù)據(jù)包中的序號,然后再發(fā)送出去給主機 A。
在規(guī)定的時候間內(nèi),源主機如果沒有接到 ICMP 的應(yīng)答包,則說明目標(biāo)主機不可達;如果接收到了 ICMP 回送響應(yīng)消息,則說明目標(biāo)主機可達。
此時,源主機會檢查,用當(dāng)前時刻減去該數(shù)據(jù)包最初從源主機上發(fā)出的時刻,就是 ICMP 數(shù)據(jù)包的時間延遲。
針對上面發(fā)生的事情,總結(jié)成了如下圖:
當(dāng)然這只是最簡單的,同一個局域網(wǎng)里面的情況。如果跨網(wǎng)段的話,還會涉及網(wǎng)關(guān)的轉(zhuǎn)發(fā)、路由器的轉(zhuǎn)發(fā)等等。
但是對于 ICMP 的頭來講,是沒什么影響的。會影響的是根據(jù)目標(biāo) IP 地址,選擇路由的下一跳,還有每經(jīng)過一個路由器到達一個新的局域網(wǎng),需要換 MAC 頭里面的 MAC 地址。
說了這么多,可以看出 ping 這個程序是使用了 ICMP 里面的 ECHO REQUEST(類型為 8 ) 和 ECHO REPLY (類型為 0)。
traceroute —— 差錯報文類型的使用
有一款充分利用 ICMP 差錯報文類型的應(yīng)用叫做 traceroute
(在UNIX、MacOS中是這個命令,而在Windows中對等的命令叫做 tracert )。
1. traceroute 作用一
traceroute 的第一個作用就是故意設(shè)置特殊的 TTL,來追蹤去往目的地時沿途經(jīng)過的路由器。
traceroute 的參數(shù)指向某個目的 IP 地址:
traceroute 192.168.1.100
這個作用是如何工作的呢?
它的原理就是利用 IP 包的生存期限 從 1
開始按照順序遞增的同時發(fā)送 UDP 包,強制接收 ICMP 超時消息的一種方法。
比如,將 TTL 設(shè)置 為 1
,則遇到第一個路由器,就犧牲了,接著返回 ICMP 差錯報文網(wǎng)絡(luò)包,類型是時間超時。
接下來將 TTL 設(shè)置為 2
,第一個路由器過了,遇到第二個路由器也犧牲了,也同意返回了 ICMP 差錯報文數(shù)據(jù)包,如此往復(fù),直到到達目的主機。
這樣的過程,traceroute 就可以拿到了所有的路由器 IP。
當(dāng)然有的路由器根本就不會返回這個 ICMP,所以對于有的公網(wǎng)地址,是看不到中間經(jīng)過的路由的。
發(fā)送方如何知道發(fā)出的 UDP 包是否到達了目的主機呢?
traceroute 在發(fā)送 UDP
包時,會填入一個不可能的端口號值作為 UDP 目標(biāo)端口號(大于 3000
)。當(dāng)目的主機,收到 UDP 包后,會返回 ICMP 差錯報文消息,但這個差錯報文消息的類型「端口不可達」。
所以,當(dāng)差錯報文類型是端口不可達時,說明發(fā)送方發(fā)出的 UDP 包到達了目的主機。
2. traceroute 作用二
traceroute 還有一個作用是故意設(shè)置不分片,從而確定路徑的 MTU。
這么做是為了什么?
這樣做的目的是為了路徑MTU發(fā)現(xiàn)。
因為有的時候我們并不知道路由器的 MTU
大小,以太網(wǎng)的數(shù)據(jù)鏈路上的 MTU
通常是 1500
字節(jié),但是非以太網(wǎng)的 MTU
值就不一樣了,所以我們要知道 MTU
的大小,從而控制發(fā)送的包大小。
它的工作原理如下:
首先在發(fā)送端主機發(fā)送 IP
數(shù)據(jù)報時,將 IP
包首部的分片禁止標(biāo)志位設(shè)置為 1。根據(jù)這個標(biāo)志位,途中的路由器不會對大數(shù)據(jù)包進行分片,而是將包丟棄。
隨后,通過一個 ICMP 的不可達消息將數(shù)據(jù)鏈路上 MTU 的值一起給發(fā)送主機,不可達消息的類型為「需要進行分片但設(shè)置了不分片位」。
發(fā)送主機端每次收到 ICMP 差錯報文時就減少包的大小,以此來定位一個合適的 MTU
值,以便能到達目標(biāo)主機。
參考文獻
[1] 竹下隆史.圖解TCP/IP.人民郵電出版社.
[2] 劉超.趣談網(wǎng)絡(luò)協(xié)議.極客時間.
輕松時刻
來了,它還是來了,倉鼠時刻 ,嘿嘿!
最后如果你覺得本文或倉鼠不錯,“關(guān)注+轉(zhuǎn)發(fā)+再看”,一條龍走起,我就當(dāng)你打賞了 66.6 元了。
Goodbye,我們下次見!
推薦閱讀
探究!一個數(shù)據(jù)包在網(wǎng)絡(luò)中的心路歷程
硬核!30 張圖解 HTTP 常見的面試題
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!