1999, 20 February
pingを行うプログラム |
Windowsで、pingを行うプログラムを作る場合は rawソケットを使って実現するというのが正統なやりかただとは思うのですが、あまり知られていない(?)と思われる IcmpSendEchoを使用するとちょっと楽をできます。
使用するヘッダファイルは、ipexport.h と icmpapi.hです。主要部分を以下に示します。
int icmp_echo(struct in_addr& inaddr, DWORD timeout)
{
DWORD cnt;
unsigned char request_data[32];
unsigned char reBuff[sizeof(ICMP_ECHO_REPLY)+200];
ICMP_ECHO_REPLY *p;
IP_OPTION_INFORMATION ipopt,*pipopt;
HANDLE hIcmpFH;
int maxhops=20;
int stat=FALSE;
hIcmpFH=IcmpCreateFile();
if(hIcmpFH<0){
return -1;
}
pipopt=NULL;
if(maxhops){
memset(&ipopt,0,sizeof(ipopt));
ipopt.Ttl=maxhops;
ipopt.OptionsData=request_data;
pipopt = &ipopt;
}
memset(reBuff,0,sizeof(ICMP_ECHO_REPLY)+200);
memset(request_data,0,sizeof(request_data));
cnt=IcmpSendEcho(hIcmpFH,*(IPAddr *)(&inaddr.s_addr),request_data,
sizeof(request_data),pipopt,reBuff,sizeof(reBuff),timeout);
p=(ICMP_ECHO_REPLY *)reBuff;
DWORD ip=p->Address;
printf("Address %ld.%ld.%ld.%ld\n",ip&0xff,(ip>>8)&0xff,(ip>>16)&0xff,ip>>24);
printf("Status %ld\n", p->Status);
printf("RoundTripTime %ld\n", p->RoundTripTime);
printf("DataSize %d\n", p->DataSize);
if(p->Status == 0){
stat=TRUE;
}
IcmpCloseHandle(hIcmpFH);
return stat;
}
Icmp系の関数を使用するときは icmp.libをリンクするか icmp.dllを LoadLibraryして、IcmpCreateFile, IcmpCloseHandle, IcmpSendEchoを GetProcAddressして使うようにしてください。
ところで、ここで使用している構造体に、ICMP_ECHO_REPLYというものがあるのですが、このなかの ReplyStatusが何を意味するものが良くわからなかったのですが この構造体が定義してある Ipexport.h のちょっと下を見ると
//
// IP_STATUS codes returned from IP APIs
//
#define IP_STATUS_BASE 11000
#define IP_SUCCESS 0
#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
#define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
#define IP_BAD_OPTION (IP_STATUS_BASE + 7)
#define IP_HW_ERROR (IP_STATUS_BASE + 8)
#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
#define IP_BAD_REQ (IP_STATUS_BASE + 11)
#define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
//
// The next group are status codes passed up on status indications to
// transport layer protocols.
//
#define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
#define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
#define IP_UNLOAD (IP_STATUS_BASE + 22)
#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
#define MAX_IP_STATUS IP_GENERAL_FAILURE
#define IP_PENDING (IP_STATUS_BASE + 255)
っと定義されているじゃないですか... これになかなか気がつかずに色々探してしまいました。まぁこの定義だけではまだ完全な意味がわかるわけではないのですが define文の文字列からかなり想像できますからね。