Tracert-程序设计报告_第1页
Tracert-程序设计报告_第2页
Tracert-程序设计报告_第3页
Tracert-程序设计报告_第4页
Tracert-程序设计报告_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

设计报告课程计算机网络设计名称Tracert程序专业班级计科112同组人学号姓名实验日期指导教师成绩年月日一、设计目的和要求1、实验目的1.熟悉原始套接字编程。

2.了解网络的结构。

3.了解网络传输底层协议。

4.熟悉掌握

ICMP协议的工作原理和路由跟踪原理。

5.掌握vc6.0下程序调试、运行的基本方法。

6.通过实验熟悉协议的应用。2、实验要求1、通过实验,可以使程序记录并显示了数据报从源端机器传送到目标机器的过程中所经过的路由器的IP地址,并且记录了数据报到达每个路由器所需要的时间。认真观察到达每个路由器的时间有什么区别,从而熟练掌握tracert的工作原理和ICMP报文协议。

2、当我们不能通过网络访问目的设备时,网络管理员就需要判断是哪里出了问题。问题不仅仅会出现在最终目的设备,也可能出现在转发数据包的中间路由器。二、设计说明(包括设计分析,系统运行环境,设计中的重点和难点,输入和输出输出条件等)路由是把信息从源穿过网络传递到目的地的行为,在传输过程中,遇到一系列的中间节点。这些中间节点构成了路由跟踪的依据。路由跟踪是在路由的基础上提出的问题,是利用路由跟踪实用程序于确定IP数据报访问目标所采取的路径。当我们不能通过网络访问目的设备时,网络运行者就需要判断是哪里出了问题。问题不仅仅会出现在最终目的设备,也可能出现在转发数据包的中间路由器。解决方法是了解了IP数据报访问目标所采取的路径,将发现网络布网简单拓扑,确定路由断点即可解决网络故障。操作系统中的tracert或traceroute路由跟踪程序,通过它可以查看到达目标地址所经过的路径。它的作用与ping有类似之处使用ping可以检查是否连接,如果不通,一般不好准确判断哪一个节点出错,而使用tracert则可以准确判断出错的部分。系统实现路由的跟踪,每经过一个路由,要求得到经过该路由节点的地址,也就是说输入目标信息,可以得到本地主机到目标经过的所有中间节点。这些中间节点用IP地址标识。并要求对跟踪跳数,每一跳等待时间可控。为了让系统更加完善,首先要测试目标的连通性,系统中也要实现目标探测功能,即Ping功能。当数据报从你的计算机经过多个网关传送到目的地时,Tracert命令可以用来跟踪数据报使用的路由(路径)。该实用程序跟踪的路径是源计算机到目的地的一条路径,不能保证或认为数据报总遵循这个路径。Tracert是一个运行得比较慢的命令(如果你指定的目标地址比较远),每个路由器你大约需要给它15秒钟。

Tracert使用时只需要在tracert后面跟一个IP地址或URL,Tracert会进行相应的域名转换,Tracert一般用来检测故障的位置,你可以用tracertIP在哪个环节上出了问题,虽然还是没有确定是什么问题,但它已经告诉了我们问题所在的地方。

三、系统详细设计(包括程序流程、主要函数等)开始开始使用UDP协议创建原始UDP包使用UDP协议创建原始UDP包目的主机回应答或达到最大跳站目的主机回应答或达到最大跳站 YTTL++(初始值为1)NTTL++(初始值为1)填充UDP数据包并发送填充UDP数据包并发送有数据报到达? N有数据报到达?有预期数据报? Y有预期数据报? NY解析数据报并显示输出超时,显示超时信息解析数据报并显示输出超时,显示超时信息释放各种资源显示结果信息释放各种资源显示结果信息结束结束四、程序源代码及注释#include<iostream.h>#include<iomanip.h>#include<winsock2.h>#include<ws2tcpip.h>#include"itracert.h"////////////////////////////////////////////////////////intmain(intargc,char*argv[]){ //检查命令行参数 if(argc!=2) { cerr<<"\nUsage:itracertip_or_hostname\n"; return-1; } //初始化winsock2环境 WSADATAwsa; if(WSAStartup(MAKEWORD(2,2),&wsa)!=0) { cerr<<"\nFailedtoinitializetheWinSock2DLL\n" <<"errorcode:"<<WSAGetLastError()<<endl; return-1; } //将命令行参数转换为IP地址 u_longulDestIP=inet_addr(argv[1]); if(ulDestIP==INADDR_NONE) { //转换不成功时按域名解析 hostent*pHostent=gethostbyname(argv[1]); if(pHostent) { ulDestIP=(*(in_addr*)pHostent->h_addr).s_addr; //输出屏幕信息 cout<<"\nTracingrouteto"<<argv[1] <<"["<<inet_ntoa(*(in_addr*)(&ulDestIP))<<"]" <<"withamaximumof"<<DEF_MAX_HOP<<"hops.\n"<<endl; } else//解析主机名失败 { cerr<<"\nCouldnotresolvethehostname"<<argv[1]<<'\n' <<"errorcode:"<<WSAGetLastError()<<endl; WSACleanup(); return-1; } } else { //输出屏幕信息 cout<<"\nTracingrouteto"<<argv[1] <<"withamaximumof"<<DEF_MAX_HOP<<"hops.\n"<<endl; } //填充目的Socket地址 sockaddr_indestSockAddr; ZeroMemory(&destSockAddr,sizeof(sockaddr_in)); destSockAddr.sin_family=AF_INET; destSockAddr.sin_addr.s_addr=ulDestIP; //使用ICMP协议创建RawSocket SOCKETsockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED); if(sockRaw==INVALID_SOCKET) { cerr<<"\nFailedtocreatearawsocket\n" <<"errorcode:"<<WSAGetLastError()<<endl; WSACleanup(); return-1; } //设置端口属性 intiTimeout=DEF_ICMP_TIMEOUT; if(setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&iTimeout,sizeof(iTimeout))==SOCKET_ERROR) { cerr<<"\nFailedtosetrecvtimeout\n" <<"errorcode:"<<WSAGetLastError()<<endl; closesocket(sockRaw); WSACleanup(); return-1; } if(setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&iTimeout,sizeof(iTimeout))==SOCKET_ERROR) { cerr<<"\nFailedtosetsendtimeout\n" <<"errorcode:"<<WSAGetLastError()<<endl; closesocket(sockRaw); WSACleanup(); return-1; } //创建ICMP包发送缓冲区和接收缓冲区 charIcmpSendBuf[sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE]; memset(IcmpSendBuf,0,sizeof(IcmpSendBuf)); charIcmpRecvBuf[MAX_ICMP_PACKET_SIZE]; memset(IcmpRecvBuf,0,sizeof(IcmpRecvBuf)); //填充待发送的ICMP包 ICMP_HEADER*pIcmpHeader=(ICMP_HEADER*)IcmpSendBuf; pIcmpHeader->type=ICMP_ECHO_REQUEST; pIcmpHeader->code=0; pIcmpHeader->id=(USHORT)GetCurrentProcessId(); memset(IcmpSendBuf+sizeof(ICMP_HEADER),'E',DEF_ICMP_DATA_SIZE); //开始探测路由 DECODE_RESULTstDecodeResult; BOOLbReachDestHost=FALSE; USHORTusSeqNo=0; intiTTL=1; intiMaxHop=DEF_MAX_HOP; while(!bReachDestHost&&iMaxHop--) { //设置IP数据报头的ttl字段 setsockopt(sockRaw,IPPROTO_IP,IP_TTL,(char*)&iTTL,sizeof(iTTL)); //输出当前跳站数作为路由信息序号 cout<<setw(3)<<iTTL<<flush; //填充ICMP数据报剩余字段 ((ICMP_HEADER*)IcmpSendBuf)->cksum=0; ((ICMP_HEADER*)IcmpSendBuf)->seq=htons(usSeqNo++); ((ICMP_HEADER*)IcmpSendBuf)->cksum=GenerateChecksum((USHORT*)IcmpSendBuf,sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE); //记录序列号和当前时间 stDecodeResult.usSeqNo=((ICMP_HEADER*)IcmpSendBuf)->seq; stDecodeResult.dwRoundTripTime=GetTickCount(); //发送ICMP的EchoRequest数据报 if(sendto(sockRaw,IcmpSendBuf,sizeof(IcmpSendBuf),0, (sockaddr*)&destSockAddr,sizeof(destSockAddr))==SOCKET_ERROR) { //如果目的主机不可达则直接退出 if(WSAGetLastError()==WSAEHOSTUNREACH) cout<<'\t'<<"Destinationhostunreachable.\n" <<"\nTracecomplete.\n"<<endl; closesocket(sockRaw); WSACleanup(); return0; } //接收ICMP的EchoReply数据报 //因为收到的可能并非程序所期待的数据报,所以需要循环接收直到收到所要数据或超时 sockaddr_infrom; intiFromLen=sizeof(from); intiReadDataLen; while(1) { //等待数据到达 iReadDataLen=recvfrom(sockRaw,IcmpRecvBuf,MAX_ICMP_PACKET_SIZE, 0,(sockaddr*)&from,&iFromLen); if(iReadDataLen!=SOCKET_ERROR)//有数据包到达 { //解码得到的数据包,如果解码正确则跳出接收循环发送下一个EchoRequest包 if(DecodeIcmpResponse(IcmpRecvBuf,iReadDataLen,stDecodeResult)) { if(stDecodeResult.dwIPaddr.s_addr==destSockAddr.sin_addr.s_addr) bReachDestHost=TRUE; cout<<'\t'<<inet_ntoa(stDecodeResult.dwIPaddr)<<endl; break; } } elseif(WSAGetLastError()==WSAETIMEDOUT)//接收超时,打印星号 { cout<<setw(9)<<'*'<<'\t'<<"Requesttimedout."<<endl; break; } else { cerr<<"\nFailedtocallrecvfrom\n" <<"errorcode:"<<WSAGetLastError()<<endl; closesocket(sockRaw); WSACleanup(); return-1; } } //TTL值加1 iTTL++; } //输出屏幕信息 cout<<"\nTracecomplete.\n"<<endl; closesocket(sockRaw); WSACleanup(); return0;}//产生网际校验和USHORTGenerateChecksum(USHORT*pBuf,intiSize){ unsignedlongcksum=0; while(iSize>1) { cksum+=*pBuf++; iSize-=sizeof(USHORT); } if(iSize) cksum+=*(UCHAR*)pBuf; cksum=(cksum>>16)+(cksum&0xffff); cksum+=(cksum>>16); return(USHORT)(~cksum);}//解码得到的数据报BOOLDecodeIcmpResponse(char*pBuf,intiPacketSize,DECODE_RESULT&stDecodeResult){ //检查数据报大小的合法性 IP_HEADER*pIpHdr=(IP_HEADER*)pBuf; intiIpHdrLen=pIpHdr->hdr_len*4; if(iPacketSize<(int)(iIpHdrLen+sizeof(ICMP_HEADER))) returnFALSE; //按照ICMP包类型检查id字段和序列号以确定是否是程序应接收的Icmp包 ICMP_HEADER*pIcmpHdr=(ICMP_HEADER*)(pBuf+iIpHdrLen); USHORTusID,usSquNo; if(pIcmpHdr->type==ICMP_ECHO_REPLY) { usID=pIcmpHdr->id; usSquNo=pIcmpHdr->seq; } elseif(pIcmpHdr->type==ICMP_TIMEOUT) { char*pInnerIpHdr=pBuf+iIpHdrLen+sizeof(ICMP_HEADER); //载荷中的IP头 intiInnerIPHdrLen=((IP_HEADER*)pInnerIpHdr)->hdr_len*4;//载荷中的IP头长 ICMP_HEADER*pInnerIcmpHdr=(ICMP_HEADER*)(pInnerIpHdr+iInnerIPHdrLen);//载荷中的ICMP头 usID=pInnerIcmpHdr->id; usSquNo=pInnerIcmpHdr->seq; } else returnFALSE; if(usID!=(USHORT)GetCurrentProcessId()||usSquNo!=stDecodeResult.usSeqNo) returnFALSE; //处理正确收到的ICMP数据报 if(pIcmpHdr->type==ICMP_ECHO_REPLY|| pIcmpHdr->type==ICMP_TIMEOUT) { //返回解码结果 stDecodeResult.dwIPaddr.s_addr=pIpHdr->sourceIP; stDecodeResult.dwRoundTripTime=GetTickCount()-

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论