Tracert 程序设计报告Word文档格式.docx
- 文档编号:17215799
- 上传时间:2022-11-29
- 格式:DOCX
- 页数:12
- 大小:152.73KB
Tracert 程序设计报告Word文档格式.docx
《Tracert 程序设计报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《Tracert 程序设计报告Word文档格式.docx(12页珍藏版)》请在冰豆网上搜索。
解决方法是了解了IP数据报访问目标所采取的路径,将发现网络布网简单拓扑,确定路由断点即可解决网络故障。
操作系统中的tracert或traceroute路由跟踪程序,通过它可以查看到达目标地址所经过的路径。
它的作用与ping有类似之处使用ping可以检查是否连接,如果不通,一般不好准确判断哪一个节点出错,而使用tracert则可以准确判断出错的部分。
系统实现路由的跟踪,每经过一个路由,要求得到经过该路由节点的地址,也就是说输入目标信息,可以得到本地主机到目标经过的所有中间节点。
这些中间节点用IP地址标识。
并要求对跟踪跳数,每一跳等待时间可控。
为了让系统更加完善,首先要测试目标的连通性,系统中也要实现目标探测功能,即Ping功能。
当数据报从你的计算机经过多个网关传送到目的地时,Tracert命令可以用来跟踪数据报使用的路由(路径)。
该实用程序跟踪的路径是源计算机到目的地的一条路径,不能保证或认为数据报总遵循这个路径。
Tracert是一个运行得比较慢的命令(如果你指定的目标地址比较远),每个路由器你大约需要给它15秒钟。
Tracert使用时只需要在tracert后面跟一个IP地址或URL,Tracert会进行相应的域名转换,Tracert一般用来检测故障的位置,你可以用tracertIP在哪个环节上出了问题,虽然还是没有确定是什么问题,但它已经告诉了我们问题所在的地方。
三、系统详细设计(包括程序流程、主要函数等)
Y
N
N
Y
四、程序源代码及注释
#include<
iostream.h>
iomanip.h>
winsock2.h>
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)
\nFailedtoinitializetheWinSock2DLL\n"
<
errorcode:
<
WSAGetLastError()<
endl;
//将命令行参数转换为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"
}
else//解析主机名失败
cerr<
\nCouldnotresolvethehostname"
argv[1]<
'
\n'
WSACleanup();
return-1;
else
//输出屏幕信息
cout<
//填充目的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)
\nFailedtocreatearawsocket\n"
WSACleanup();
//设置端口属性
intiTimeout=DEF_ICMP_TIMEOUT;
if(setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&
iTimeout,sizeof(iTimeout))==SOCKET_ERROR)
\nFailedtosetrecvtimeout\n"
closesocket(sockRaw);
if(setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&
\nFailedtosetsendtimeout\n"
//创建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;
code=0;
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));
//输出当前跳站数作为路由信息序号
setw(3)<
iTTL<
flush;
//填充ICMP数据报剩余字段
((ICMP_HEADER*)IcmpSendBuf)->
cksum=0;
seq=htons(usSeqNo++);
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"
closesocket(sockRaw);
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<
inet_ntoa(stDecodeResult.dwIPaddr)<
break;
}
}
elseif(WSAGetLastError()==WSAETIMEDOUT)//接收超时,打印星号
setw(9)<
*'
Requesttimedout."
break;
else
cerr<
\nFailedtocallrecvfrom\n"
closesocket(sockRaw);
WSACleanup();
return-1;
//TTL值加1
iTTL++;
//输出屏幕信息
cout<
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->
elseif(pIcmpHdr->
type==ICMP_TIMEOUT)
char*pInnerIpHdr=pBuf+iIpHdrLen+sizeof(ICMP_HEADER);
//载荷中的IP头
intiInnerIPHdrLen=((IP_HEADER*)pInnerIpHdr)->
//载荷中的IP头长
ICMP_HEADER*pInnerIcmpHdr=(ICMP_HEADER*)(pInnerIpHdr+iInnerIPHdrLen);
//载荷中的ICMP头
usID=pInnerIcmpHdr->
usSquNo=pInnerIcmpHdr->
if(usID!
=(USHORT)GetCurrentProcessId()||usSquNo!
=stDecodeResult.usSeqNo)
//处理正确收到的ICMP数据报
type==ICMP_ECHO_REPLY||
pIcmpHdr->
//返回解码结果
stDecodeResult.dwIPaddr.s_addr=pIpHdr->
sourceIP;
stDecodeResult.dwRoundTripTime=GetTickCount()-stDecodeResult.dwRoundTripTime;
//打印屏幕信息
if(stDecodeResult.dwRoundTripTime)
setw(6)<
stDecodeResult.dwRoundTripTime<
ms"
else
1"
returnTRUE;
returnFALSE;
五、实验数据、结果分析
该程序将包含不同生存时间(TTL)值的Internet控制消息协议(ICMP)回显数据包发送到目标,以决定到达目标采用的路由。
要在转发数据包上的TTL之前至少递减1,必需路径上的每个路由器,所以TTL是有效的跃点计数。
数据包上的TTL到达0时,路由器应该将“ICMP已超时”的消息发送回源系统。
Tracert先发送TTL为1的回显数据包,并在随后的每次发送过程将TTL递增1,直到目标响应或TTL达到最大值,从而确定路由。
路由通过检查中级路由器发送回的“ICMP已超时”的消息来确定路由。
六、总结
路由追踪的过程是,源主机向目的主机发送一个类为8的回应请求报文,若目的站收到回应请求报文,则把把报文IP包头部中的目的IP与源主机的IP地址交换,将类型为8改为回应类型0,计算出新的校验和再发往源主机。
若源主机受到了该回应报文,则不但说明了,目的主机可达,而且说明目的主机与源主机之间的路由器工作正常。
源主机和目的主机的IP、ICMP软件运行正常。
但若在传播过程中出现了某些问题,如网络不通、目的主机不在网络中等,导致数据被定向一个无效的目的地,这时相关的路由器或目的主机将发回目的不可达报文,并在代码中说明该报文的具体情况:
是网络不可达还是主机不可达等。
若请求报文在传播过程中超时,即TTL被减为0(报文每经过一个路由器TTL都要减1,则该路由器返回一个TTL超时报文(类型为11),报文IP头中源IP地址即为本路由器的IP地址。
七、教师意见
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Tracert 程序设计报告 程序设计 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)