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