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