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. react-native构建基本页面2---轮播图+九宫格

    配置首页的轮播图 轮播图官网 运行npm i react-native-swiper --save安装轮播图组件 导入轮播图组件import Swiper from 'react-native-swi ...

  2. ubuntu安装配置heirloom-mailx使用外部smtp发送外网email

    1- 安装 1.1- 添加heirloom-mailx apt源 cat /etc/apt/sources.list.d/mailx.list deb http://cz.archive.ubuntu ...

  3. Android Studio阶段性学习总结_1

    这半个月一直在学习Android方面的知识,对Android开发有了一个基本的认识,学会了Android studio的基本操作. 在建立第一个Android studio项目时,我遇到了很大的阻碍, ...

  4. vue.js 的cdn 链接的引用地址

    引用地址有两种一种完整版,一种压缩版效果是一样的 https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js https://cdn.bootcss.com ...

  5. Appium学习2-Appium-desktop的使用

    安装: 下载路径:https://github.com/appium/appium-desktop/releases 选择最新的安装包即可. 使用 1.点击打开应用程序,进入到配置项. 2.配置以下信 ...

  6. Attention machenism

    from attention mechanism Attention is one component of a network’s architecture, and is in charge of ...

  7. vue里使用elementUI里的下拉树表格,如何定义个性化的子表格?

    最近项目写到一个业务,首先需要展示各类分组的基本信息,然后需要点击每个分组展示该分组下子的所有具体信息 一开始我是打算用tab来展示就是首先父分组的名称就是各个不同的tab按钮,然后点击按钮再展示不同 ...

  8. centos6.8安装教程

    特别详细的一个安装教程以及镜像下载等,用虚拟机不会安装或者安装失败的可以参考一下. https://blog.csdn.net/wu_zeqin/article/details/79833046

  9. 题解【洛谷P3574】[POI2014]FAR-FarmCraft

    题面 简化版题意: 有一棵 \(n\) 个点的树,有边权. 你初始在 \(1\) 号节点,你需要走遍整棵树为 \(2 \sim n\) 号点的居民分发电脑,但你的汽油只够经过每条边恰好两次. 一个居民 ...

  10. print format

    python基础_格式化输出(%用法和format用法) name = 'jack' age = 18 sex = 'man' job = "IT" salary = 9999.9 ...