大部分人用ping命令只是作為查看另一個系統的網絡連接是否正常的一種簡單方法。在這篇文章中,作者將介紹如何用語言編寫一個模擬ping命令功能的程序。
ping命令是用來查看網絡上另一個主機系統的網絡連接是否正常的一個工具。ping命令的工作原理是:向網絡上的另一個主機系統發送ICMP報文,如果指定系統得到了報文,它將把報文一模一樣地傳回給發送者,這有點象潛水艇聲納中使用的發聲裝置。
例如,在Linux終端上執行ping localhost命令將會看到以下結果:
PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=112 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=79 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=255 time=78 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=255 time=82 usec
--- localhost.localdomain ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/mdev = 0.078/0.087/0.112/0.018 ms
由上面的執行結果可以看到,ping命令執行後顯示出被測試系統主機名和相應IP地址、返回給當前主機的ICMP報文順序號、ttl生存時間和往返時間rtt(單位是毫秒,即千分之一秒)。要寫一個模擬ping命令,這些信息有啟示作用。
要真正了解ping命令實現原理,就要了解ping命令所使用到的TCP/IP協議。
ICMP(Internet Control Message,網際控制報文協議)是為網關和目標主機而提供的一種差錯控制機制,使它們在遇到差錯時能把錯誤報告給報文源發方。ICMP協議是IP層的一個協議,但是由於差錯報告在發送給報文源發方時可能也要經過若干子網,因此牽涉到路由選擇等問題,所以ICMP報文需通過IP協議來發送。ICMP數據報的數據發送前需要兩級封裝:首先添加ICMP報頭形成ICMP報文,再添加IP報頭形成IP數據報。如下圖所示
IP報頭 ICMP報頭 ICMP數據報IP報頭格式
由於IP層協議是一種點對點的協議,而非端對端的協議,它提供無連接的數據報服務,沒有端口的概念,因此很少使用bind()和connect()函數,若有使用也只是用於設置IP地址。發送數據使用sendto()函數,接收數據使用recvfrom()函數。IP報頭格式如下圖: