?? icmp.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 + -