Ping命令的实现(转)

PING (Packet InterNet Groper) 是一个非常有用的命令,它可以用来测试两个主机之间的连通性.PING使用了ICMP回送请求与回送回答报文.PING是应用层直接使用网络层ICMP的一个例子.它没有通过运输层的TCP或UDP.

     在Windows平台编程实现PING的最简单方法是调用Iphlpapi.dll这个动态链接库,引用以下几个函数:

     1. IcmpCreateFile(); // opens a handle on which IPv4 ICMP echo requests can be issued.

     2. IcmpSendEcho(); // sends an IPv4 ICMP echo request and returns any echo response replies.

                                  // The call returns when the time-out has expired or the reply buffer is filled.

     3. IcmpCloseHandle(); // closes a handle opened by a call to the IcmpCreateFile or Icmp6CreateFile functions.

以下是实现代码:

 

 //    Ping.c
 //
 //    利用ICMP回送请求与回答报文模拟Ping命令
 //
 //    Step:
 //    1. Open ICMP handle
 //    2. Sends an IPv4 ICMP echo request and returns any echo response replies.
 //    3. Display the infomation for response echo.
 //    4. Close ICMP handle
 //
 //    Configuration before Build Solution:
 //    Project->Properties->Linker->Input->Addtional Dependencies : Iphlpapi.lib Ws2_32.lib
 

 #include <winsock2.h>
 #include <iphlpapi.h>
 #include <icmpapi.h>
 #include <stdio.h>
 
 int main( int argc, char ** argv )
 {
     /* 声明并初始化变量 */
     HANDLE hIcmp = INVALID_HANDLE_VALUE;
     unsigned long ulDestIpAddr = INADDR_NONE;
     char sendBuffer [] = "Send Buffer";
     LPVOID lpReplyBuffer = NULL;
     int iReplySize = 0;
     DWORD dwTimeout = 1000;
     DWORD dwRetVal = 0;
 
     /* 打开ICMP句柄    */
     hIcmp = IcmpCreateFile ();
     if ( INVALID_HANDLE_VALUE == hIcmp )
     {
         printf ( "Open ICMP failure!\n" );
         return EXIT_FAILURE;
     }
 
     /* 验证命令行参数 */
     if ( argc != 2 )
     {
         printf ( "Usage : %s IP Address\n", argv[0] );
         IcmpCloseHandle( hIcmp );
         return EXIT_FAILURE;
     }
 
     ulDestIpAddr = inet_addr ( argv[1] );
     if ( *argv[1] == INADDR_NONE )
     {
         printf ( "Usage : %s IP Address\n", argv[0] );
         IcmpCloseHandle( hIcmp );
         return EXIT_FAILURE;
     }
 
     iReplySize = sizeof ( ICMP_ECHO_REPLY ) + sizeof ( sendBuffer );
     lpReplyBuffer = malloc ( iReplySize );
 
     /* 发送ICMP报文并等待回送请求 */
     dwRetVal = IcmpSendEcho ( hIcmp, ulDestIpAddr, sendBuffer, sizeof(sendBuffer),
         NULL, lpReplyBuffer, iReplySize, dwTimeout );
     if ( 0 != dwRetVal )
     {
         // 利用一指针获取 Request Echo 的 ICMP_ECHO_REPLY 结构实例
         PICMP_ECHO_REPLY pReplyEcho = (PICMP_ECHO_REPLY) lpReplyBuffer;
 
         in_addr replyIpAddr;
         replyIpAddr.S_un.S_addr = pReplyEcho->Address;
         printf ( "Reply from : %s\n", inet_ntoa(replyIpAddr) );
 
         if ( dwRetVal > 1 )
         {
             printf ( "Retrieved %d ICMP response message.\n", dwRetVal );
             printf ( "----The infomation for the first message.----\n" );
         }
        else
         {
             printf ( "Retrieved %d ICMP reponse message.\n", dwRetVal );
             printf ( "----The information for the message.----\n" );
         }
         
         printf ( "The status : %ld\n", pReplyEcho->Status );
         printf ( "The reply data : %s\n", pReplyEcho->Data );
         printf ( "The Roundtrip time : %ld milliseconds.\n", pReplyEcho->RoundTripTime );
     }
     else
     {
         printf ( "ICMP send failure.\n" );
         printf ( "The IcmpSendEcho call error : %ld\n", GetLastError() );
         IcmpCloseHandle( hIcmp );
         return EXIT_FAILURE;
     }
  
     /* 关闭ICMP句柄 */
     IcmpCloseHandle( hIcmp );
 
     return EXIT_SUCCESS;
 
}
posted @ 2009-04-11 08:26  木瓜脑袋  阅读(1194)  评论(0编辑  收藏  举报