⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icmp.cpp

📁 实现tracert
💻 CPP
字号:
 // ICMP.cpp: implementation of the CICMP class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "RouteTrace.h"
#include "ICMP.h"
#include "ws2tcpip.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CICMP::CICMP()
{
	winsock = 0;
	m_pIp = NULL;
	m_pIcmp = NULL;

	m_pIp = (IP_HEAD *)new BYTE[MAX_PACKET];
	m_pIcmp = (ICMP_HEAD *)new BYTE[MAX_PACKET];

}

CICMP::~CICMP()
{
	delete [] m_pIp;
	delete [] m_pIcmp;
}


BOOL CICMP::Initialize()
{
	WSADATA wsadata;
	if( WSAStartup(MAKEWORD(2, 1),&wsadata) )   
	{
		AfxMessageBox("WSAStartup初始化失败!");
		return FALSE;
	}
	
	winsock= WSASocket (AF_INET,  	//建立socket

				   SOCK_RAW,
				   IPPROTO_ICMP,
				   NULL, 0,0);
	if(!winsock)	{
		AfxMessageBox( "Socket创建失败!");
		return FALSE;
	}

	int timeout =5000;
	setsockopt(winsock,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,   // 设置接收超时
		sizeof(timeout));
	timeout = 5000;
	setsockopt(winsock,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,    //设置发送超时
		sizeof(timeout));

	return TRUE;
}

void CICMP::Uninitialize()                //释放Socket
{
	if(winsock)
		closesocket(winsock);
	WSACleanup();
}

USHORT CICMP::CheckSum(USHORT *buffer, int size)  //计算校验和
{
  unsigned long cksum = 0;
  while(size > 1) {
	cksum+=*buffer++;
	size -=sizeof(USHORT);
  }
  
  if(size ) {
	cksum += *(UCHAR*)buffer;
  }

  cksum = (cksum >> 16) + (cksum & 0xffff);
  cksum += (cksum >>16);

  return (USHORT)(~cksum);

}

BOOL CICMP::SendICMPPack(char *pAddr)
{
	sockaddr_in sockAddr;
	memset((void *)&sockAddr,0,sizeof(sockAddr));
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_port = 0;
	sockAddr.sin_addr.S_un.S_addr=inet_addr(pAddr);

	return SendICMPPack(&sockAddr);
}
//--------------------发送---------------------------
BOOL CICMP::SendICMPPack(sockaddr_in *pAddr)
{
	//填充ICMP数据各项
	int  state;
	char *p_data;
	m_pIcmp->type = ICMP_ECHO;
	m_pIcmp->code = 0;
	m_pIcmp->ID = (USHORT)GetCurrentProcessId();//一定要用当前进程的么?
	m_pIcmp->number = 0;
	m_pIcmp->time = GetTickCount();
	m_pIcmp->cksum = 0;

	//填充数据
	p_data = ((char *)m_pIcmp + sizeof(ICMP_HEAD));
	memset((char *)p_data,'0',DEF_PACKET);

	//检查和
	m_pIcmp->cksum = CheckSum((USHORT *)m_pIcmp,
		DEF_PACKET+sizeof(ICMP_HEAD));
	
	//发送数据
	state = sendto(winsock,(char *)m_pIcmp,
		DEF_PACKET+sizeof(ICMP_HEAD),
		NULL,(struct sockaddr *)pAddr,sizeof(sockaddr));

	if(state == SOCKET_ERROR) {
		if(GetLastError()==WSAETIMEDOUT)
			m_strInfo = "连接超时!(发送)";
		else
			m_strInfo="出现未知发送错误!";
		return FALSE;
	}

	if(state <DEF_PACKET) {
		m_strInfo = "发送数据错误!";
		return FALSE;
	}
	
	memcpy((void *)&m_sockAddr,(void *)pAddr,
		sizeof(sockaddr_in));

	return TRUE;
}

//----------------------接收数据----------------------------
BOOL CICMP::RecvICMPPack()
{
	int state;
	int len = sizeof(sockaddr_in);
	char * addr;
    struct hostent *lpHostent = NULL;

	addr = inet_ntoa(m_sockAddr.sin_addr);
	state = recvfrom(winsock,(char *)m_pIp,MAX_PACKET,0,
		(struct sockaddr*)&m_sockAddr,&len);

	if (state == SOCKET_ERROR) {
		if (WSAGetLastError() == WSAETIMEDOUT)
		{	m_strInfo.Format("接收超时,路由跟踪失败!");
		routestate=0;
		RouteState="路由跟踪失败!";
		}
		else
			m_strInfo = "未知接收错误!";
		return FALSE;
	}

	//分析数据
	int ipheadlen;
	ipheadlen = m_pIp->HeadLen * 4 ;

	if (state < (ipheadlen+MIN_PACKET))	{
		m_strInfo = "目的地址的响应数据不正确";
		return FALSE;
	}

	ICMP_HEAD * p_icmprev;
	p_icmprev = (ICMP_HEAD*)((char *)m_pIp + ipheadlen);

    	switch (p_icmprev->type)
		{
		case ICMP_ECHOREPLY:  //收到正常回显
		{
		m_strInfo.Format("接收到%s  %d字节响应数据,响应时间:%dms.",
		inet_ntoa(m_sockAddr.sin_addr),len,GetTickCount()-p_icmprev->time);
		routeaddr=addr;
		routestate=0;	
	    RouteState="到达目的主机!";
	    return TRUE;
			break;	
		}
		case ICMP_TTLOUT:   // TTL超时
		{   routeaddr=inet_ntoa(m_sockAddr.sin_addr);
			routestate=1;
			RouteState="测试到路由器!";
			return TRUE;
			break;
		}
		
		case ICMP_DESUNREACH:  //目的不可达
		{	m_strInfo = "目的不可达!";
		   	routestate=0;
			RouteState="目的不可达!";
			return TRUE;
			break;
		}
				
		default :{  routestate=0;
					m_strInfo="未知错误!";
					RouteState="不明状态!";
				 }
		}
		return TRUE;

}
//----------------设置TTL--------------------
int CICMP::SetTTL(int TTL)
{
	int nRet=setsockopt(winsock, IPPROTO_IP, IP_TTL,(LPSTR)&TTL,sizeof(int));
    
	if(nRet==SOCKET_ERROR)
	{   CString ttlerr;
		ttlerr.Format("设置 TTL 错误!");
		AfxMessageBox(ttlerr);
		return 0;
	}
	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -