网络通信程序设计实验二路由跟踪.docx
《网络通信程序设计实验二路由跟踪.docx》由会员分享,可在线阅读,更多相关《网络通信程序设计实验二路由跟踪.docx(12页珍藏版)》请在冰豆网上搜索。
网络通信程序设计实验二路由跟踪
实验报告
课程名称网络通信程序设计
实验仪器计算机
实验名称路由跟踪
系别__计算机学院_
专业___
班级/学号__
学生姓名
实验日期2014年4月6日
成绩___________________
指导教师焦健
实验二路由跟踪实验
一、实验目的
学习分析程序功能结构。
熟悉ICMP协议的工作原理和路由跟踪的原理。
掌握VC6.0下程序调试、运行的基本方法。
二、实验原理
路由跟踪的实现就是巧妙地利用了ICMP报文的TTL超时报文。
其实现过程如下:
源主机先向目的主机发送一个回应请求报文(类型8),TTL值设为1,第一个路由器收到后将TTL减1,这样TTL变为0,分组被废除。
同时路由器向源主机发送一个TTL超时报文(类型为11),报文的IP包头中的源IP地址就是第一个路由器的地址,源主机就可以通过对该报文进行分析,得到第一个路由器的地址。
接着发送TTL等于2的报文得到第二个路由器地址,再发TTL等于3的报文。
如此下去直到收到目的主机的回应应答报文(类型为0)或目的不可达报文(类型为3),或者到了最大跳数(要检测路由器个数的最大值)。
可以看到,对TTL的设置是实现跟踪的关键,使用函数setsockopt(m_Sock,IPPROTO_IP,IP_TTL,(LPSTR)&TTL,sizeof(int))可以对其进行设置,m_Sock是所创建的套接字,IP_TTL说明是进行TTL设置,TTL即是要设置的TTL值,为一个整形数值。
其实现流程如图1所示:
图1路由跟踪流程图
三、实验内容
1、按照附录内容给RouteTrace程序添加代码,增加注释,调试程序通过。
源代码:
RouteTrace.cpp
//RouteTrace.cpp:
Definestheclassbehaviorsfortheapplication.
#include"stdafx.h"
#include"RouteTrace.h"
#include"RouteTraceDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CRouteTraceApp
BEGIN_MESSAGE_MAP(CRouteTraceApp,CWinApp)
//{{AFX_MSG_MAP(CRouteTraceApp)
//NOTE-theClassWizardwilladdandremovemappingmacroshere.
//DONOTEDITwhatyouseeintheseblocksofgeneratedcode!
//}}AFX_MSG
ON_COMMAND(ID_HELP,CWinApp:
:
OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CRouteTraceAppconstruction
CRouteTraceApp:
:
CRouteTraceApp()
{
//TODO:
addconstructioncodehere,
//PlaceallsignificantinitializationinInitInstance
}
/////////////////////////////////////////////////////////////////////////////
//TheoneandonlyCRouteTraceAppobject
CRouteTraceApptheApp;
/////////////////////////////////////////////////////////////////////////////
//CRouteTraceAppinitialization
BOOLCRouteTraceApp:
:
InitInstance()
{
AfxEnableControlContainer();
//Standardinitialization
//Ifyouarenotusingthesefeaturesandwishtoreducethesize
//ofyourfinalexecutable,youshouldremovefromthefollowing
//thespecificinitializationroutinesyoudonotneed.
#ifdef_AFXDLL
Enable3dControls();//CallthiswhenusingMFCinasharedDLL
#else
Enable3dControlsStatic();//CallthiswhenlinkingtoMFCstatically
#endif
CRouteTraceDlgdlg;
m_pMainWnd=&dlg;
intnResponse=dlg.DoModal();
if(nResponse==IDOK)
{//TODO:
Placecodeheretohandlewhenthedialogis
//dismissedwithOK
}
elseif(nResponse==IDCANCEL)
{
//TODO:
Placecodeheretohandlewhenthedialogis
//dismissedwithCancel
}
//Sincethedialoghasbeenclosed,returnFALSEsothatweexitthe
//application,ratherthanstarttheapplication'smessagepump.
returnFALSE;
}
源代码:
ICMP.cpp
//ICMP.cpp:
implementationoftheCICMPclass.
#include"stdafx.h"
#include"RouteTrace.h"
#include"ICMP.h"
#include"ws2tcpip.h"
#ifdef_DEBUG
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#definenewDEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
//Construction/Destruction
//////////////////////////////////////////////////////////////////////
CICMP:
:
CICMP()
{winsock=0;
m_pIp=NULL;
m_pIcmp=NULL;
m_pIp=(IP_HEAD*)newBYTE[MAX_PACKET];
m_pIcmp=(ICMP_HEAD*)newBYTE[MAX_PACKET];
}
CICMP:
:
~CICMP()
{delete[]m_pIp;
delete[]m_pIcmp;
}
BOOLCICMP:
:
Initialize()
{WSADATAwsadata;
if(WSAStartup(MAKEWORD(2,1),&wsadata))
{AfxMessageBox("WSAStartup初始化失败!
");
returnFALSE;
}
winsock=WSASocket(AF_INET,//建立socket
SOCK_RAW,
IPPROTO_ICMP,
NULL,0,0);
if(!
winsock){
AfxMessageBox("Socket创建失败!
");
returnFALSE;}
inttimeout=5000;
setsockopt(winsock,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,// 设置接收超时
sizeof(timeout));
timeout=5000;
setsockopt(winsock,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,//设置发送超时
sizeof(timeout));
returnTRUE;
}
voidCICMP:
:
Uninitialize()//释放Socket
{
if(winsock)
closesocket(winsock);
WSACleanup();
}
USHORTCICMP:
:
CheckSum(USHORT*buffer,intsize)//计算校验和
{
unsignedlongcksum=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);
}
BOOLCICMP:
:
SendICMPPack(char*pAddr)
{sockaddr_insockAddr;
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);
returnSendICMPPack(&sockAddr);
}
//----------------设置TTL--------------------
intCICMP:
:
SetTTL(intTTL)
{intnRet=setsockopt(winsock,IPPROTO_IP,IP_TTL,(LPSTR)&TTL,sizeof(int));
if(nRet==SOCKET_ERROR)
{CStringttlerr;
ttlerr.Format("设置TTL错误!
");
AfxMessageBox(ttlerr);
return0;
}
return1;
}
//--------------------发送---------------------------
BOOLCICMP:
:
SendICMPPack(sockaddr_in*pAddr)
{//填充ICMP数据各项
intstate;
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,(structsockaddr*)pAddr,sizeof(sockaddr));
if(state==SOCKET_ERROR){
if(GetLastError()==WSAETIMEDOUT)
m_strInfo="连接超时!
(发送)";
else
m_strInfo="出现未知发送错误!
";
returnFALSE;
}
if(statem_strInfo="发送数据错误!
";
returnFALSE;
}
memcpy((void*)&m_sockAddr,(void*)pAddr,
sizeof(sockaddr_in));
returnTRUE;
}
//----------------------接收数据----------------------------
BOOLCICMP:
:
RecvICMPPack()
{
intstate;
intlen=sizeof(sockaddr_in);
char*addr;
structhostent*lpHostent=NULL;
intMaxfd=1;//监视的最大的文件描述符值+1
fd_setreadFdSet;//设置文件描述符
structtimevalTimeout;
addr=inet_ntoa(m_sockAddr.sin_addr);
FD_ZERO(&readFdSet);
FD_SET(winsock,&readFdSet);
Maxfd=max(Maxfd,winsock)+1;
Timeout.tv_sec=10;//设置响应时间限制
Timeout.tv_usec=0;
inte=:
:
select(Maxfd,&readFdSet,NULL,NULL,&Timeout);//获取多路复用套接字的响应结果
if(e<=0){
routeaddr="****";
routestate=1;
RouteState="超时未知";
returnFALSE;
}
if(!
FD_ISSET(winsock,&readFdSet))
returnFALSE;
state=recvfrom(winsock,(char*)m_pIp,MAX_PACKET,0,(structsockaddr*)&m_sockAddr,&len);
if(state==SOCKET_ERROR){
if(WSAGetLastError()==WSAETIMEDOUT)
{
m_strInfo.Format("接收超时,路由跟踪失败!
");
routestate=0;
RouteState="路由跟踪失败!
";
}
else
m_strInfo="未知接收错误!
";
returnFALSE;
}
//分析数据
intipheadlen;
ipheadlen=m_pIp->HeadLen*4;
if(state<(ipheadlen+MIN_PACKET)){
m_strInfo="目的地址的响应数据不正确";
returnFALSE;
}
ICMP_HEAD*p_icmprev;
p_icmprev=(ICMP_HEAD*)((char*)m_pIp+ipheadlen);
switch(p_icmprev->type)
{
caseICMP_ECHOREPLY:
//收到正常回显
{
m_strInfo.Format("接收到%s%d字节响应数据,响应时间:
%dms.",
inet_ntoa(m_sockAddr.sin_addr),len,GetTickCount()-p_icmprev->time);
routeaddr=addr;
routestate=0;
RouteState="到达目的主机!
";
returnTRUE;
break;
}
caseICMP_TTLOUT:
//TTL超时
{
routeaddr=inet_ntoa(m_sockAddr.sin_addr);
routestate=1;
RouteState="测试到路由器!
";
returnTRUE;
break;
}
caseICMP_DESUNREACH:
//目的不可达
{m_strInfo="目的不可达!
";
routestate=0;
RouteState="目的不可达";
returnTRUE;
break;
}
default:
{routestate=0;
routeaddr="***";
m_strInfo="未知错误!
";
RouteState="不明状态!
";
}
}
returnTRUE;
}
2、命令行窗口下运行:
tracert命令,记录运行结果和网站IP地址。
3、用RouteTrace程序执行到2中网站IP的路由跟踪,记录结果。
4、由于该程序在编制过程中没有考虑路由器不返回应答报文这一情况,因此程序在未收到报文的情况下执行处理流程存在显示错误,请找出问题所在的代码将其更正,正确显示为如下的结果:
四、实验要求及注意事项
代码主要内容已经添加了注释,重点理解ICMP.cpp中接收数据部分的代码。
充分利用网络搜索,查找相关资料。
五、实验总结
此次实验主要是学习分析程序功能结构,在VisualC++6.0中调试通过,从而熟悉ICMP协议的工作原理和路由跟踪的原理。
同时还可以根据实际需要修改程序中的参数,通过这次学习对路由跟踪有了更深刻的认识。