Linux ping的原理与实现
1. ping過程:
我們以下面一個網(wǎng)絡(luò)為例:有A、B、C、D四臺機子,一臺路由RA,子網(wǎng)掩碼均為255.255.255.0,默認網(wǎng)關(guān)為192.168.0.1
1、在同一網(wǎng)段內(nèi)
在主機A上運行“Ping 192.168.0.5”后,都發(fā)生了些什么呢? 首先,Ping命令會構(gòu)建一個固定格式的ICMP請求數(shù)據(jù)包,然后由ICMP協(xié)議將這個數(shù)據(jù)包連同地址“192.168.0.5”一起交給IP層協(xié)議(和ICMP一樣,實際上是一組后臺運行的進程),IP層協(xié)議將以地址“192.168.0.5”作為目的地址,本機IP地址作為源地址,加上一些其他的控制信息,構(gòu)建一個IP數(shù)據(jù)包,并想辦法得到192.168.0.5的MAC地址(物理地址,這是數(shù)據(jù)鏈路層協(xié)議構(gòu)建數(shù)據(jù)鏈路層的傳輸單元——幀所必需的),以便交給數(shù)據(jù)鏈路層構(gòu)建一個數(shù)據(jù)幀。關(guān)鍵就在這里,IP層協(xié)議通過機器B的IP地址和自己的子網(wǎng)掩碼,發(fā)現(xiàn)它跟自己屬同一網(wǎng)絡(luò),就直接在本網(wǎng)絡(luò)內(nèi)查找這臺機器的MAC,如果以前兩機有過通信,在A機的ARP緩存表應(yīng)該有B機IP與其MAC的映射關(guān)系,如果沒有,就發(fā)一個ARP請求廣播,得到B機的MAC,一并交給數(shù)據(jù)鏈路層。后者構(gòu)建一個數(shù)據(jù)幀,目的地址是IP層傳過來的物理地址,源地址則是本機的物理地址,還要附加上一些控制信息,依據(jù)以太網(wǎng)的介質(zhì)訪問規(guī)則,將它們傳送出去。
主機B收到這個數(shù)據(jù)幀后,先檢查它的目的地址,并和本機的物理地址對比,如符合,則接收;否則丟棄。接收后檢查該數(shù)據(jù)幀,將IP數(shù)據(jù)包從幀中提取出來,交給本機的IP層協(xié)議。同樣,IP層檢查后,將有用的信息提取后交給ICMP協(xié)議,后者處理后,馬上構(gòu)建一個ICMP應(yīng)答包,發(fā)送給主機A,其過程和主機A發(fā)送ICMP請求包到主機B一模一樣。
2、不在同一網(wǎng)段內(nèi)
在主機A上運行“Ping 192.168.1.4”后,開始跟上面一樣,到了怎樣得到MAC地址時,IP協(xié)議通過計算發(fā)現(xiàn)D機與自己不在同一網(wǎng)段內(nèi),就直接將交由路由處理,也就是將路由的MAC取過來,至于怎樣得到路由的MAC,跟上面一樣,先在ARP緩存表找,找不到就廣播。路由得到這個數(shù)據(jù)幀后,再跟主機D進行聯(lián)系,如果找不到,就向主機A返回一個超時的信息。
?
2. iputils軟件包:
執(zhí)行ping -V:
baoli@ubuntu:~$ ping -V
ping utility, iputils-s20161105
可知ping命令屬于iputils軟件包,參考: iputils軟件包
?
ping過程中會涉及兩種協(xié)議:
-
ICMP
-
ARP:查找MAC地址
?
ping報文格式:
MAC + IP + ICMP
?
iputils中ping相關(guān)文件:
-
ping.c
-
ping6.c
-
ping_common.c
?
3. ping代碼實現(xiàn)流程:
1. 首先創(chuàng)建raw socket:icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
2. 處理命令行選項
3. 如果沒有指定源IP(網(wǎng)絡(luò)接口),需要 創(chuàng)建probe_fd = socket(AF_INET, SOCK_DGRAM, 0),然后通過getsockname()找到源地址。
4. 通過setsockopt()設(shè)置各種選項
5.?bind:bind(icmp_sock, (struct sockaddr*)&source, sizeof(source))
6. 發(fā)送icmp報文:pinger(),在send_probe()中先構(gòu)造struct icmphdr *icp,然后通過sendmsg發(fā)送出去。
7. 接收ICMP消息:recvmsg(icmp_sock, &msg, polling),再通過parse_reply()解析消息。
8. 已達指定次數(shù)、ctrl+c等退出處理。其中ctrl+c利用Linux?signal實現(xiàn)。
????set_signal(SIGINT, sigexit);
????set_signal(SIGALRM, sigexit);
????set_signal(SIGQUIT, sigstatus);
?
總結(jié)
以上是生活随笔為你收集整理的Linux ping的原理与实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《流浪地球2》周边众筹超3500万 商家
- 下一篇: linux C bool变量