C3Lab研究室

Back to Title Page(OpenLab)タイトルページへ戻る

最終更新日: 1999年 08月 26日 木曜日

*Network Software構築シリーズ6 Winsock1.1でPINGする

 今回は、ニュースグループで質問のあった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__

C++クラスファイルの内容


#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