最終更新日: 1999年 08月 26日 木曜日
今回は、ニュースグループで質問のあったPINGクラスを公開いたします。詳しい使用法などはいずれ
別の場所で公開予定になっていますので、ヘッダーやクラスの内部構造を理解できる方は使用してみて
ください。
このコードはWPINGおよびSCK99を作成するのに使用したコードをC++のクラスに変換したものです。
void OnKillfocusEdit1() { CString hostname; CPing ping; char hostaddr[4]; LPHOSTENT sHost; { // TimeOut CString s; m_edit2.GetWindowText(s); ping.SetTimeOutTime(LPCTSTR(s)); } m_edit1.GetWindowText(hostname); if(hostname.GetLength()==0)return; if(ping.GetHostName(hostname,hostname,hostaddr,&sHost)==TRUE){ int n; m_edit1.SetWindowText(hostname); m_add1.SetAddress( hostaddr[0],hostaddr[1],hostaddr[2],hostaddr[3]); n = iplist.AddList(sHost); while(1){ if(ping.GetHostName(hostname,hostname,hostaddr,&sHost)==FALSE)break; if(iplist.Compare(n,sHost)==0)break; int n2; n2 = iplist.AddList(sHost); break; } }else{ AfxMessageBox("サーバーIPアドレスが修得できませんでした"); return; } }
// // // Ping.h // #ifndef __PING_HDR__ #define __PING_HDR__ #include#pragma pack(1) #define ICMP_ECHOREPLY 0 #define ICMP_ECHOREQ 8 // IP Header -- RFC 791 typedef struct tagIPHDR { u_char VIHL; // Version and IHL u_char TOS; // Type Of Service short TotLen; // Total Length short ID; // Identification short FlagOff; // Flags and Fragment Offset u_char TTL; // Time To Live u_char Protocol; // Protocol u_short Checksum; // Checksum struct in_addr iaSrc; // Internet Address - Source struct in_addr iaDst; // Internet Address - Destination }IPHDR, *PIPHDR; // ICMP Header - RFC 792 typedef struct tagICMPHDR { u_char Type; // Type u_char Code; // Code u_short Checksum; // Checksum u_short ID; // Identification u_short Seq; // Sequence char Data; // Data }ICMPHDR, *PICMPHDR; #define REQ_DATASIZE 32 // Echo Request Data size // ICMP Echo Request typedef struct tagECHOREQUEST { ICMPHDR icmpHdr; DWORD dwTime; char cData[REQ_DATASIZE]; }ECHOREQUEST, *PECHOREQUEST; // ICMP Echo Reply typedef struct tagECHOREPLY { IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller[256]; }ECHOREPLY, *PECHOREPLY; #pragma pack() ///////////////////////////// class CPing : public CObject { public: CPing(); virtual ~CPing(); public: CString errstr; private: int timeout; private: u_short in_cksum(u_short *addr, int len); public: void ReportError (LPCTSTR s); int SendEchoRequest (SOCKET s,LPSOCKADDR_IN lpstToAddr); DWORD RecvEchoReply (SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL); int WaitForEchoReply (SOCKET s); public: int GetTimeOutTime(void); void SetTimeOutTime(int s); void SetTimeOutTime(LPCTSTR s); public: DWORD Ping(unsigned long addr,LPDWORD pdwElapsed=NULL,unsigned char * pcTTL=NULL); DWORD Ping(LPCSTR pstrHost,LPDWORD pdwElapsed=NULL,unsigned char* pTTL =NULL); BOOL GetHostName(LPCTSTR pstrHost,CString &hostname,char *hostaddr=NULL,LPHOSTENT* lpDesc=NULL); }; #endif // __PING_HDR__
#include "ping.h" #pragma comment(lib, "wsock32.lib") CPing::CPing(){ timeout = 5; WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1, 1); int nResult = WSAStartup(wVersionRequested, &wsaData); if (nResult != 0)return ; if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){ // Version Error Job return ; } errstr=""; }; CPing::~CPing(){ WSACleanup(); }; int CPing::GetTimeOutTime(void){return timeout;}; void CPing::SetTimeOutTime(int s){timeout=s;}; void CPing::SetTimeOutTime(LPCTSTR s){ SetTimeOutTime(atoi(s)); }; void CPing::ReportError(LPCTSTR s){ errstr=s; }; int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) { static ECHOREQUEST echoReq; static nId = 1; static nSeq = 1; int nRet; echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId++; echoReq.icmpHdr.Seq = nSeq++; for (nRet = 0; nRet < REQ_DATASIZE; nRet++) echoReq.cData[nRet] = ' '+nRet; echoReq.dwTime = GetTickCount(); echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); nRet = sendto(s,(LPSTR)&echoReq, sizeof(ECHOREQUEST), 0,(LPSOCKADDR)lpstToAddr, sizeof(SOCKADDR_IN)); if (nRet == SOCKET_ERROR) ReportError("sendto()"); return (nRet); }; DWORD CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) { ECHOREPLY echoReply; int nRet; int nAddrLen = sizeof(struct sockaddr_in); nRet = recvfrom(s,(LPSTR)&echoReply,sizeof(ECHOREPLY),0,(LPSOCKADDR)lpsaFrom,&nAddrLen); if (nRet == SOCKET_ERROR) ReportError("recvfrom()"); *pTTL = echoReply.ipHdr.TTL; return(echoReply.echoRequest.dwTime); }; int CPing::WaitForEchoReply(SOCKET s){ struct timeval Timeout; fd_set readfds; readfds.fd_count = 1; readfds.fd_array[0] = s; Timeout.tv_sec = timeout; Timeout.tv_usec = 0; return(select(1, &readfds, NULL, NULL, &Timeout)); }; u_short CPing::in_cksum(u_short *addr, int len){ register int nleft = len; register u_short *w = addr; register u_short answer; register int sum = 0; while( nleft > 1 ) { sum += *w++; nleft -= 2; } if( nleft == 1 ) { u_short u = 0; *(u_char *)(&u) = *(u_char *)w ; sum += u; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return (answer); }; ///////////////////////////////////////////////////////////// DWORD CPing::Ping(LPCSTR pstrHost,LPDWORD pdwElapsed,unsigned char * pcTTL){ SOCKET rawSocket; LPHOSTENT lpHost; struct sockaddr_in saDest; struct sockaddr_in saSrc; DWORD dwTimeSent; DWORD dwElapsed; u_char cTTL; int nRet; CString sbk,s; // *pcTTL = (unsigned char)-1; *pdwElapsed = (DWORD)-1; rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket == SOCKET_ERROR) {ReportError("socket()"); return -1; } lpHost = gethostbyname(pstrHost); if (lpHost == NULL){ char buf[80]; wsprintf(buf,"\nHost not found: %s\n", pstrHost); ReportError(buf); return -1; } saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr)); saDest.sin_family = AF_INET; saDest.sin_port = 0; while(1){ SendEchoRequest(rawSocket, &saDest); nRet = WaitForEchoReply(rawSocket); if (nRet == SOCKET_ERROR){ ReportError("select()");break;} if (!nRet){ ReportError("TimeOut"); break;} dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL); dwElapsed = GetTickCount() - dwTimeSent; break; } nRet = closesocket(rawSocket); if(pdwElapsed!=NULL)*pdwElapsed=dwElapsed; if(pcTTL!=NULL)*pcTTL=cTTL; if (nRet == SOCKET_ERROR) {ReportError("closesocket()"); return -1;} return dwElapsed; } DWORD CPing::Ping(unsigned long addr,LPDWORD pdwElapsed,unsigned char * pcTTL){ SOCKET rawSocket; struct sockaddr_in saDest; struct sockaddr_in saSrc; DWORD dwTimeSent; DWORD dwElapsed =-1; u_char cTTL=-1; int nRet; CString sbk,s; // *pcTTL = (unsigned char)-1; *pdwElapsed = (DWORD)-1; rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket == SOCKET_ERROR) {ReportError("socket()"); return -1; } saDest.sin_addr.s_addr = addr; saDest.sin_family = AF_INET; saDest.sin_port = 0; while(1){ SendEchoRequest(rawSocket, &saDest); nRet = WaitForEchoReply(rawSocket); if (nRet == SOCKET_ERROR){ ReportError("select()");break;} if (!nRet){ ReportError("TimeOut"); break;} dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL); dwElapsed = GetTickCount() - dwTimeSent; break; } nRet = closesocket(rawSocket); if(pdwElapsed!=NULL)*pdwElapsed=dwElapsed; if(pcTTL!=NULL)*pcTTL=cTTL; if (nRet == SOCKET_ERROR) {ReportError("closesocket()"); return -1;} return dwElapsed; } BOOL CPing::GetHostName(LPCTSTR pstrHost,CString &hostname,char *hostaddr,LPHOSTENT *lpDesc){ SOCKET rawSocket; LPHOSTENT lpHost; int nRet; CString sbk,s; rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket == SOCKET_ERROR) {ReportError("socket()"); return FALSE; } lpHost = gethostbyname(pstrHost); if (lpHost == NULL){ char buf[80]; wsprintf(buf,"\nHost not found: %s\n", pstrHost); ReportError(buf); return FALSE; } if(lpHost->h_aliases!=NULL){ hostname = *lpHost->h_aliases; if(hostname.GetLength()==0)hostname = lpHost->h_name; }else hostname = lpHost->h_name; if(lpDesc!=NULL)*lpDesc=lpHost; if(hostaddr!=NULL){ for(int i=0;i<4;i++){ char *p = *lpHost->h_addr_list; hostaddr[i] = p[i]; } } nRet = closesocket(rawSocket); if (nRet == SOCKET_ERROR) {ReportError("closesocket()"); return FALSE;} return TRUE; }
Copyright (C) Kitaro 1999