https://blog.csdn.net/u013271921/article/details/45488173

#include<winsock2.h>
//#include<iphlpapi.h>
#include <Ws2tcpip.h>
#include<iostream>
#include<conio.h>
//#include<bits/stdc++.h>
using namespace std; const BYTE ICMP_ECHO_REQUEST = ;//请求回显
const BYTE ICMP_ECHO_REPLY = ;//回显应答
const BYTE ICMP_TIMEOUT = ;//传输超时
const int DEF_ICMP_DAtA_SIZE = ;//ICMP报文默认数据字段长度
const int MAX_ICMP_PACKET_SIZE = ;//ICMP报文最大长度(包含报头)
const DWORD DEF_ICMP_TIMEOUT = ;//回显应答超时时间,单位ms
const int DEF_MAX_HOP = ;//最大跳站数 typedef struct {
BYTE hdr_len :;//4位头部长度
BYTE version :;//长度版本号
BYTE tos;//8位服务类型
USHORT total_len;//16位总长度
USHORT identifier;//16位标识符
USHORT frag_and_flags;//3位标志+13位片偏移
BYTE ttl;//8位生存时间
BYTE protocol;//8位上层协议号
USHORT checksum;//16位校验和
ULONG sourceIP;//32位源IP地址
ULONG destIP;//32位目的IP地址
} IP_HEADER; typedef struct {
BYTE type;//8位类型字段
BYTE code;//8位代码字段
USHORT cksum;//16为校验和
USHORT id;//16位标识符
USHORT seq;//16位序列号
} ICMP_HEADER; typedef struct {
// 序列号(输入参数)
USHORT usSeqNo;
// 往返时间(输入、输出)
DWORD dwRoundTripTime;
// 返回报文的IP地址(输出参数)
in_addr dwIpAddr;
} DECODE_RESULT; //计算网际校验和函数
USHORT checksum(USHORT* pBuf, int iSize) {
ULONG cksum = ;
while(iSize > ) {
cksum += *pBuf++;
iSize -= sizeof(USHORT);
}
// 如果 iSize 为正,即为奇数个字节
if(iSize) {
// 则在末尾补上一个字节,使之有偶数个字节
cksum += *(UCHAR*)pBuf;
}
cksum = (cksum>>) +(cksum & 0xffff);
cksum += (cksum >> );
return (USHORT)(~cksum);
} bool DecodeIcmpResponse(char *pBuf, int iPacketSize, DECODE_RESULT& DecodeResult) {
// 计算IP头部长度
int iIpHdrLen = ((IP_HEADER*)pBuf)->hdr_len * ;
// 根据ICMP报文类型提取ID字段和序列号字段
ICMP_HEADER *pIcmpHdr = (ICMP_HEADER *)(pBuf + iIpHdrLen);
USHORT usID;
USHORT usSquNo;
// ICMP回显应答报文
if(pIcmpHdr->type == ICMP_ECHO_REPLY) {
// 报文ID
usID = pIcmpHdr->id;
// 序列号
usSquNo = pIcmpHdr->seq;
}
// ICMP超时差错报文
else if(pIcmpHdr->type == ICMP_TIMEOUT) {
// 载荷中的IP头
char *pInnerIpHdr = pBuf + iIpHdrLen + sizeof(ICMP_HEADER);
// 载荷中的IP头长
int iInnerIpHdrLen = ((IP_HEADER*)pInnerIpHdr)->hdr_len * ;
// 载荷中的ICMP头
ICMP_HEADER *pInnerIcmpHdr = (ICMP_HEADER*)(pInnerIpHdr + iInnerIpHdrLen);
// 报文ID
usID = pInnerIcmpHdr->id;
// 序列号
usSquNo = pInnerIcmpHdr->seq;
}
else {
return false;
}
// printf("usID: %d == currentID: %d\n", usID, (USHORT)GetCurrentProcessId());
// printf("usSquNo: %d == DecodeResult: %d\n", usSquNo, DecodeResult.usSeqNo);
// 检查ID和序列号以确定收到期待数据报
if(usID != (USHORT)GetCurrentProcessId() || usSquNo != DecodeResult.usSeqNo) {
return false;
}
// 记录IP地址并计算往返时间
DecodeResult.dwIpAddr.s_addr = ((IP_HEADER*)pBuf)->sourceIP;
DecodeResult.dwRoundTripTime = GetTickCount() - DecodeResult.dwRoundTripTime;
// 打印往返时间信息
if(DecodeResult.dwRoundTripTime) {
cout << " " << DecodeResult.dwRoundTripTime << "ms" << flush;
}
else {
cout << " " << "<1" << "ms" << flush;
}
return true;
} WSADATA wsa;
char IcmpSendBuf[sizeof(ICMP_HEADER) + DEF_ICMP_DAtA_SIZE];//发送缓冲区
char IcmpRecvBuf[sizeof(ICMP_HEADER) + DEF_ICMP_DAtA_SIZE];//接收缓冲区
char argv[][];
int main() {
WSAStartup(MAKEWORD(, ), &wsa);
//将命令行参数转换成IP地址
scanf("%s", argv[]);
ULONG ulDestIP = inet_addr(argv[]);
if(ulDestIP == INADDR_NONE) {
//转换不成功时按域名解析
hostent *pHostent = gethostbyname(argv[]);
if(pHostent) ulDestIP = (*(in_addr*) pHostent->h_addr).s_addr;
else {
WSACleanup();
return -;
}
}
//填充目的端socket地址。
sockaddr_in destSockAddr;
ZeroMemory(&destSockAddr, sizeof(sockaddr_in));
destSockAddr.sin_family = AF_INET;
destSockAddr.sin_addr.s_addr = ulDestIP;
SOCKET sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, , WSA_FLAG_OVERLAPPED);
int iTimeout = ;
//设置超时机制
setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*) &iTimeout, sizeof(iTimeout));
setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*) &iTimeout, sizeof(iTimeout));
ICMP_HEADER *pIcmpHeader = (ICMP_HEADER*) IcmpSendBuf;
pIcmpHeader->type = ICMP_ECHO_REQUEST;//类型为请求回显
pIcmpHeader->code = ;//代码字段为0
pIcmpHeader->id=(USHORT)GetCurrentProcessId();//ID字段为当前进程号
memset(IcmpSendBuf + sizeof(ICMP_HEADER), 'E', DEF_ICMP_DAtA_SIZE);//数据字段
USHORT usSeqNo = ;//ICMP报文序列号
int iTTL = ;//TTL初始值为1
bool bReachDestHost = false;//循环退出标志
int iMaxHop = DEF_MAX_HOP;//循环的最大次数
DECODE_RESULT DecodeResult;//传递给报文解码函数的结构化参数
while(!bReachDestHost && iMaxHop--) {
//设置IP报头的TTL字段
setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char*)&iTTL, sizeof(iTTL));
cout << iTTL << flush;//输出当前序号
//填充ICMP报文中每次发送时需要变化的字段
((ICMP_HEADER*)IcmpSendBuf)->cksum = ;//校验和先置为0
((ICMP_HEADER*)IcmpSendBuf)->seq = htons(usSeqNo++);//填充序列号
//计算校验和
((ICMP_HEADER*)IcmpSendBuf)->cksum = checksum((USHORT*)IcmpSendBuf, sizeof(ICMP_HEADER) + DEF_ICMP_DAtA_SIZE);
DecodeResult.usSeqNo = ((ICMP_HEADER*)IcmpSendBuf)->seq;//当前序号
DecodeResult.dwRoundTripTime = GetTickCount();//当前时间
//发送ICMP回显请求消息
sendto(sockRaw, IcmpSendBuf, sizeof(IcmpSendBuf), , (sockaddr*)&destSockAddr, sizeof(destSockAddr));
// 接收ICMP报文
// 对端Socket地址
sockaddr_in from;
// 地址结构大小
int iFromLen = sizeof(from);
// 接收数据长度
int iReadDataLen;
// 循环接收直到收到所需数据或超时
while() {
iReadDataLen = recvfrom(sockRaw, IcmpRecvBuf, MAX_ICMP_PACKET_SIZE, , (sockaddr*)&from, &iFromLen);
// 有数据到达
if(iReadDataLen != SOCKET_ERROR) {
// 对数据包进行解析
if(DecodeIcmpResponse(IcmpRecvBuf, iReadDataLen, DecodeResult)) {
// 到达目的地,退出循环
if(DecodeResult.dwIpAddr.s_addr == destSockAddr.sin_addr.s_addr) {
bReachDestHost = true;
// printf("reach\n");
}
// 打印IP地址
cout << '\t' << inet_ntoa(DecodeResult.dwIpAddr) << endl;
break;
}
}
// 接收超时,打印*号
else if(WSAGetLastError() == WSAETIMEDOUT) {
cout << " " << '*' << '\t' << "Request timed out." << endl;
break;
}
}
iTTL++;
}
cout << "reach: " << bReachDestHost << endl;
return ;
} //cqupt 202.202.32.35
//csdn 39.96.126.153
//cnblogs 101.37.113.127

基于icmp的tracert路由追踪程序的更多相关文章

  1. ping命令基于ICMP协议的返回信息分析

    Ping是潜水艇人员的专用术语,表示回应的声纳脉冲,在网络中 Ping 是一个十分好用的 TCP/IP 工具.它主要的功能是用来检测网络的连通情况和分析网络速度.可以利用 PING 命令检查网络连通状 ...

  2. 建立tracert路由列表的方法

    建立tracert路由列表的方法:电脑屏幕左下方 选择开始选项运行 输入 CMD在DOS命令行下输入:tracert (你的网站域名)   运行结果中如出现了“*     *     *    req ...

  3. 第二百六十四节,Tornado框架-基于正则的动态路由映射分页数据获取计算

    Tornado框架-基于正则的动态路由映射分页数据获取计算 分页基本显示数据 第一步.设置正则路由映射配置,(r"/index/(?P<page>\d*)", inde ...

  4. 第二百六十三节,Tornado框架-基于正则的动态路由映射

    Tornado框架-基于正则的动态路由映射 1.在路由映射条件里用正则匹配访问路径后缀2.给每一个正则匹配规则(?P<设置名称>)设置一个名称,3.在逻辑处理的get()方法或post() ...

  5. tracert路由跟踪命令分析判断

    可能有的会使用路由跟踪命令 ,可是却看不太明确显示出来的结果.结合我的来说明一下. (1)tracert命令介绍 tracert是路由跟踪命令,通过该命令的返回结果,能够获得本地到达目标主机所经过的网 ...

  6. tracert路由跟踪工具使用方法

    1. 路由跟踪在线Tracert工具说明 Tracert(跟踪路由)是路由跟踪实用程序,用于确定 IP 数据报访问目标所采取的路径.Tracert 命令用 IP 生存时间 (TTL) 字段和 ICMP ...

  7. 基于TCAM 的高速路由查找

    摘要 随着路由器接口速率的提高,传统的软件路由查找机制已经不能满足要求.目前常见的硬件解决方案是采用TCAM实现关键词 TCAM,路由查找,最长前缀匹配. 1.引言 路由器转发IP 分组时,转发引擎需 ...

  8. tracert 路由跟踪程序

    C:\Users\Administrator>tracert 10.0.0.1 通过最多 30 个跃点跟踪到 10.0.0.1 的路由 1 <1 毫秒 1 ms 3 ms 192.168. ...

  9. 基于原生PHP的路由分配实现

    对于由原生PHP写成的独立PHP框架,利用单一入口文件实现路径的访问.这时我们会遇到的首要问题是:文件的相互包含,其次就是路由分配.当我们不利用成熟的PHP框架进行web开发时,我们就会发现上述两个问 ...

随机推荐

  1. Python中io的open()在PyCharm环境下报错和路劲的问题

    PS:我也是初学者,上班空闲时间学习学习Python.今天学到io的时候,遇到了两个用PyCharm环境编写代码的小白错误,如下: 两个问题都是如下代码: 1. 第一个问题:当写好代码之后,点击运行报 ...

  2. 12306 VS 淘宝双十一

    最近过年买票回家经常听到的一句话就是,md 12306又崩了..卧槽..心累.. 但其实有不了解的真相. 为什么12306要时不时崩一下 另一边双十一几亿人同时购物疯狂败家剁手都没有问题,为什么123 ...

  3. CSS的display显示

    CSS的display显示 1. 行内元素和块级元素关系 块级元素:1.标题标签:h1~h6:2.段落标签:p1~p6:3.div:4.列表:等 行内元素:1.span:2.a:3.img:4.str ...

  4. IndexedDB基本概念

    控制台 IndexedDB下为数据库 数据库下为表,表内容展现为主键值和其余值,其中其余值包括索引和其他任意字段,以对象形式表现 表下为索引字段表,用来展现拥有同一种索引字段的所有数据(有多少种索引就 ...

  5. ubuntu set up 4 - 设置和软件

    1. Top Bar显示日期 https://askubuntu.com/questions/966576/customizing-tray-taskbar-date-display-in-ubunt ...

  6. 剑指offer 39. 是否为平衡二叉树

    39. 是否为平衡二叉树 题目描述 输入一棵二叉树,判断该二叉树是否是平衡二叉树 任意结点的左右子树高度差不大于1就是平衡二叉树. C++解法 class Solution { public: boo ...

  7. eclipse调字体大小

    首先调java字体: Window -> Preferences -> General -> Appearance -> Colors and Fonts -> Java ...

  8. javax.naming.NameNotFoundException: Name jdbc is not bound in this Context

    这个错误的原因是没有项目使用到了Tomcat中配置的数据源(但是你本地没有配置),关于什么是JNDI看这篇文章就够了® 今天导入一个项目(比较老的),在本地运行时报错: Cannot resolve ...

  9. C# asp.net 配置文件连接sql 数据库

    先引用 using System.Configuration;//配置文件using System.Data.SqlClient; 我这里使用的是SqlServer 2008  sa 用户 密码也为s ...

  10. day03_2hibernate

    HQL.QBC详解.c3p0连接池的整合.事务的隔离级别.乐观锁.悲观锁 一.HQL详解: ①关于HQL的使用语法:[select/update/delete...][from...][类名 as  ...