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; }