//ICMP.DLL を使った ping
//使い方
//	Ping*p;
//	p=new Ping();
//	int r = p->ping("www.google.co.jp");
//
//戻り値が 0 ならばping成功
//0 以外なら失敗
//
//大量のpingを複数のターゲットに向けて送信するときは、
//複数のオブジェクトを作成してスレッドにてpingを実行しても正しく動くはずです。


#pragma comment(lib, "wsock32.lib")

#include <winsock2.h>

HANDLE     hIOMutexPing = CreateMutex (NULL, FALSE, NULL);

class Ping{
	public:
	int RTT;
	int TTL;

	int ping(char*hostname)
	{
		typedef struct {
			unsigned char Ttl;		// Time To Live
			unsigned char Tos;		// Type Of Service
			unsigned char Flags;		// IP header flags
			unsigned char OptionsSize;	// Size in bytes of options data
			unsigned char *OptionsData;	// Pointer to options data
		} IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION;

		typedef struct {
			DWORD Address;		// Replying address
			unsigned long  Status;	// Reply status
			unsigned long  RoundTripTime;	// RTT in milliseconds
			unsigned short DataSize;	// Echo data size
			unsigned short Reserved;	// Reserved for system use
			void *Data;		// Pointer to the echo data
			IP_OPTION_INFORMATION Options;// Reply options
		} IP_ECHO_REPLY, * PIP_ECHO_REPLY;
		

		WaitForSingleObject( hIOMutexPing, INFINITE );		
		WSAData wsaData;

		if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0){
			ReleaseMutex( hIOMutexPing);
			return 1;
		}

		//ホスト名のIPアドレスを調べます。
		HOSTENT*phe = gethostbyname(hostname);

		if(phe == NULL){
			ReleaseMutex( hIOMutexPing);
			return 2;
		}
		HOSTENT pHost=*phe;
		WSACleanup();
		ReleaseMutex( hIOMutexPing);

		//ICMP.DLLのロード
		HINSTANCE hIcmp = LoadLibrary("ICMP.DLL");
		if (hIcmp == 0) return 3;

		//DLLを関数ポインタに接続します。
		typedef HANDLE (WINAPI* pfnHV)(VOID);
		typedef BOOL (WINAPI* pfnBH)(HANDLE);
		typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD);
		pfnHV pIcmpCreateFile;
		pfnBH pIcmpCloseHandle;
		pfnDHDPWPipPDD pIcmpSendEcho;
		pIcmpCreateFile = (pfnHV)GetProcAddress(hIcmp,"IcmpCreateFile");
		pIcmpCloseHandle = (pfnBH)GetProcAddress(hIcmp,"IcmpCloseHandle");
		pIcmpSendEcho = (pfnDHDPWPipPDD)GetProcAddress(hIcmp,"IcmpSendEcho");

		if ((pIcmpCreateFile == 0) || (pIcmpCloseHandle == 0) || (pIcmpSendEcho == 0)) return 4;

		//開始
		HANDLE hIP = pIcmpCreateFile();
		if (hIP == INVALID_HANDLE_VALUE) return 5;

		//パケットの生成
		char acPingBuffer[64];
		memset(acPingBuffer, '\xAA', sizeof(acPingBuffer));
		PIP_ECHO_REPLY pIpe = (PIP_ECHO_REPLY)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer));
    
		if (pIpe == 0) return 6;

		pIpe->Data = acPingBuffer;
		pIpe->DataSize = sizeof(acPingBuffer);      

		//送受信
		DWORD dwStatus = pIcmpSendEcho(hIP,*((DWORD*)pHost.h_addr_list[0]),acPingBuffer,sizeof(acPingBuffer),NULL,pIpe,sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer),5000);

		//終了
		GlobalFree(pIpe);
		FreeLibrary(hIcmp);
				
		if (dwStatus != 0) {
			//Ping成功
			RTT=int(pIpe->RoundTripTime);
			TTL=int(pIpe->Options.Ttl);
			return 0;
		}else{
			//失敗
			return -1;
		}
	}
};



▲トップページ > Windows と C++