一、routetrace命令概述
routetrace命令是一种网络诊断工具,用于检测互联网协议(IP)数据包在从源到目标的传输过程中所经过的路由器。它在测量互联网连接的可用性和可靠性方面非常有用。
routetrace的工作原理是对目标主机进行一系列的ping测试,收集响应时间和具体路由信息,然后根据收集到的信息构建出网络拓扑图。这样,我们可以通过程序生成的路由路径追踪到主机,了解它的具体路径和连接状态等详细信息。
二、routetrace命令优点
1、显示网络层的路由
traceroute [destination]
routetrace命令可以帮助我们实时地获取到网络中的路由和网络延迟,以便我们更好地了解网络环境。
2、确定连接延迟的根本原因
traceroute [destination]
如果我们在网络传输过程中遇到了延迟问题,可以使用routetrace命令定位并确定延迟问题的根本原因,从而进一步解决问题。
3、灵活的定制
traceroute [destination] [-h max_hop] [-f first_hop] [-m max_ttl] [-q nqueries]
routetrace命令可以由用户按照自己的需求来设定参数,可以指定最大跳数(-h)、最小跳数(-f)、最大TTL值(-m)以及每个跳点的查询次数(-q),从而更好地定制符合自己需求的搜索路径。
三、routetrace命令注意事项
1、安全考虑
traceroute [destination]
在使用routetrace命令时,我们需要注意一定的安全问题,因为在指定ICMP数据报并在路由时遭遇限制数据包过滤器的情况下,此命令可以被黑客用来侵入目标主机。
2、路由器不稳定
traceroute [destination]
由于路由器可能有许多优化策略,从而可以造成路径的动态性和不稳定性,在进行无法保证准确度的情况下,可能会产生一些干扰。
3、路由器路由差异
traceroute [destination]
由于不同的路由器可能使用不同的路由算法,从而可能导致同一目标主机在不同的时间段,经过不同的路由器,路径或路由发生变化。
四、routetrace代码示例
#include #include #include #include #include #include void print_address(unsigned char* ip_address) { printf("%d.%d.%d.%d\t",ip_address[0],ip_address[1], ip_address[2], ip_address[3]); } unsigned short calc_checksum(unsigned char* addr,int len) { unsigned short* addr_p=(unsigned short*)addr; unsigned int sum=0; for(int i=0;i>16)+(sum&0xffff); sum=(sum>>16)+(sum&0xffff); return ~sum; } int main(int argc, char* argv[]) { int seq=0; int max_ttl=30;//最大跳数 struct sockaddr_in addr,from_addr; addr.sin_port=htons(80); addr.sin_family=AF_INET; struct hostent* hent; if((hent=gethostbyname(argv[1]))==0) { herror("无法解析目标主机!"); return -1; } memcpy(&addr.sin_addr,hent->h_addr_list[0],sizeof(addr.sin_addr)); printf("正在追踪到 %s [%s] 的路径\n",argv[1],inet_ntoa(*((struct in_addr*)hent->h_addr_list[0]))); unsigned char send_packet[64]; unsigned char recv_packet[1024]; struct ip* ipq; struct icmp* icmpq; for(int ttl=1;ttlicmp_type=ICMP_ECHO; icmpq->icmp_code=0; icmpq->icmp_seq=seq++; icmpq->icmp_id=getpid(); icmpq->icmp_cksum=calc_checksum(send_packet,sizeof(struct icmp)); int sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if(sockfd<0) { printf("创建套接字失败\n"); return -1; } printf("%d\t",ttl); for(int i=0;ih_addr_list[0]))); setsockopt(sockfd,IPPROTO_IP,IP_TTL,&ttl,sizeof(int)); struct timeval tv_val={1,0}; setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&tv_val,sizeof(tv_val));//接收超时,防止卡死 socklen_t addr_len=sizeof(from_addr); sendto(sockfd,send_packet,sizeof(send_packet),0,(struct sockaddr*)&addr,sizeof(addr)); int len=recvfrom(sockfd,recv_packet,sizeof(recv_packet),0,(struct sockaddr*)&from_addr,&addr_len); if(len>0) {//接收成功 ipq=(struct ip*)recv_packet; print_address((unsigned char*)&from_addr.sin_addr.s_addr); //打印源IP地址 printf("\t%.2lfms", (double)tv_val.tv_usec / 1000.0); //打印时间 if(ipq->ip_p==IPPROTO_ICMP) { icmpq=(struct icmp*)(recv_packet+(ipq->ip_hl<icmp_type==ICMP_TIMXCEED&&icmpq->icmp_code==ICMP_TIMXCEED_INTRANS) { printf("\t唯一跳点"); break; }else if(icmpq->icmp_type==ICMP_ECHOREPLY&&icmpq->icmp_id==getpid()) { printf("\t终点"); goto end; } } else { printf("\t*"); } } else { printf("\t超时"); } } close(sockfd); printf("\n"); } end: printf("\n"); return 0; }
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/151406.html