透析ICMP协议(五): 应用篇路由追踪

ICMP的应用之路由追踪程序(Tracert) 实现原理:Tracert 程序关键是对 IP 头部生存时间(time to live)TTL 字段的使用,程序实现是向目的主机发送一个 ICMP 回显请求报文,初始时 TTL 等于 1 ,这样当该数据报抵达途中的第一个路由器时,TTL 的值就被减为 0,导致发送超时错误,因此该路由生成一份 ICMP 超时差错报文返回给源主机。随后,主机将数据报的 TTL 值递增 1 ,以便 IP 报能传送到下一个路 阅读详情

透析ICMP协议(五):
 应用篇路由追踪
===============================
这篇文章出自bugfree/优快云
平台: VC6 Windows XP

这篇文章本应该在三天之前写完, 但是由于众所周知的原因, 我在北大bbs上转了三天, 所以这么迟才发出. 由于的懒惰导致对大家的不便, 我表示深深的道歉.


原理简介:
-------- 
   通过前四节的介绍, 可能大家对ICMP的应用有了初步的了解. 不过开始本节之前我对ICMP协议再从宏观上做些介绍. 大家都知道ICMP是为于ISO的第三层---网络层。 既是它同IP协议为于同一层, 然而大家可能也只到,ICMP协议要用到IP协议, 所以有一些书上说ICMP位ISO的第四层, 那是错误的。 同样这样那些书上这样画的的例子也是错误的, 我就发现某外资通讯公司的资料上有这样两种错误的画法
   --------------------------       
   | ICMP | TCP(SCTP)  |
   --------------------------
   |         IP                   |
   --------------------------
  
   ---------------------------
   |...        | TCP(SCTP)   |
   ---------------------------
   | ICMP |   IP                |
   ----------------------------

其实如上的画法是错误的, 正确地画法应为:
   ---------------------       
   |...   | TCP(SCTP)   |
   ---------------------
   | ICMP |                 |
   ----------                |
   |       IP                  |
   ---------------------

接下来,让我们来说明怎样实现追踪路由的功能, 大家通过我的第一节的阅读可能已经了解了超时报文的具体内容(参见透析ICMP协议(一):  协议原理), 它在如果网关在处理数据报时发现生存周期域(ttl)为零,此数据报必须抛弃。网关同时必须通过超时信息通知源主机。这是它的报文的具体结构:
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type(11)  |     Code(0/1) |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             unused                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Internet Header + 64 bits of Original Data Datagram      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

通过利用setsockopt()函数设置ICMP包的IP包头中的ttl字段便可以达到这种效果。 具体过程如下, 假设你的IP到达目标地址需要过n个路由器(n>1)。 则
 1. 初始化第一个ICMP包,并设置IP包头中的TTL为1, 则得到第一个数据路由器发回的超时报文
 2. 一般情况下:初始化第i(i<n)个ICMP包,并设置IP包头中的TTL为i, 则得到第一个数据路由器发回的超时报文

剩下的问题为如何确定超时ICMP报文的路由器IP地址得到它的机器名的信息。 这个问题可能很多读者都会求, 用gethostbyaddr()可以得到答案。

经过理论的论证后, 让我们看看如何实现。
  

具体实现:(具体如何初试化ICMP的数据包上节已有详细的介绍,这里只是补充路由追踪的代码)
--------
主要代码如下:

unsigned long ipback = 0; //超时报文的IP的初试值
unsigned long ms = 0; //超时值
struct hostent *hHost;
char m_address[256];

//直到找到目标主机, 或达到最大跳数(HOPS)
while (ipback != ipfinal){ 
 hHost = 0;


 //对到目标主机中间的某个路由器发放ping的报文(ttl为1~N-1之间)
 if (Ping(m_address,ttl,ipback,ms))
 {
  sin.sin_family = AF_INET;
  sin.sin_addr.S_un.S_addr = ipback; // 由函数返回的IP地址
    // 查找主机名
  hHost = gethostbyaddr((char*)&sin.sin_addr, 4, PF_INET);
  //这里可以输出hHost的内容
 }
 ttl++;
 if (ttl > MAX_HOPS)  //达到最大跳数
 {
  break;
 }
}

==================
ping函数的代码
==================
int Ping(const char * host, int ttl, unsigned long& ipback, unsigned long& ms)
{
 SOCKET sockRaw;
 struct sockaddr_in dest,from;
 struct hostent * hp;
 int bread,datasize;
 int fromlen = sizeof(from);
 int timeout = 100;
 char *dest_ip;
 char *icmp_data;
 char *recvbuf;
 unsigned int addr=0;
 const int MAX_PACKET = 1024;

 //初始化Socket
 sockRaw = WSASocket (AF_INET,
      SOCK_RAW,
      IPPROTO_ICMP,
      NULL, 0, WSA_FLAG_OVERLAPPED);

 if (sockRaw == INVALID_SOCKET)
 {
  // 错误
 }

   // 设置IP包头的ttl字段
 bread = setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(int));
 if(bread == SOCKET_ERROR)
 {
  // 错误
 }

 // 设置接受超时为100ms
 bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
 if(bread == SOCKET_ERROR)
 {
  // 错误
 }

 //禁止用Nagle算法缓存数据
 bread = setsockopt(sockRaw, SOL_SOCKET, TCP_NODELAY, (const char*)&killnagle, sizeof(int));
 if (bread == SOCKET_ERROR)
 {
  // 错误 
 }

 timeout = 1000;
 // 设置发送超时为100ms
 bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,
       sizeof(timeout));
 if(bread == SOCKET_ERROR)
 {
  // 错误 
 }

 //下面的代码生成ICMP包
 memset(&dest,0,sizeof(dest));
 hp = gethostbyname(host);
 if (!hp)
 {
  addr = inet_addr(host);
 }
 if ((!hp)  && (addr == INADDR_NONE) )
 {
  // 错误 
 }
 if (hp != NULL)
  memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
 else
  dest.sin_addr.s_addr = addr;

 //初始化dest
 if (hp)
  dest.sin_family = hp->h_addrtype;
 else
  dest.sin_family = AF_INET;
 
 dest_ip = inet_ntoa(dest.sin_addr);

 // 设置包长度
 datasize = DEF_PACKET_SIZE;

 // 计算包大小
 datasize += sizeof(IcmpHeader); 

 icmp_data = (char *)new[MAX_PACKET]; //分配内存,可以用new 和 delete
 recvbuf = (char *)new[MAX_PACKET];

 if (!icmp_data)
 {
  // 释放内存,退出
 }

 if (!recvbuf)
 {
  // 释放内存,退出 }
 }

 memset(icmp_data,0,MAX_PACKET);
 fill_icmp_data(icmp_data,datasize); // 这个函数用来填充ICMP的数据包

 int bwrote;
 ((IcmpHeader*)icmp_data)->i_cksum = 0;
 ((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); // 存入当前时间值
 ((IcmpHeader*)icmp_data)->i_seq = seq_no++;
 
 // 计算校验和
 ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);

  // 为了最后计算ICMP包回来的总时间
 unsigned long tc = GetTickCount();
 //发送数据包
 bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest, sizeof(dest));

 if (bwrote == SOCKET_ERROR)
 {
  // 错误
 }
 if (bwrote < datasize ) //发送字节数对否
 {
 }

 // 接受数据包
 bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,
     &fromlen);
 //计算总时间
 ms = GetTickCount() - tc;

 if (bread == SOCKET_ERROR)
 {
  // 错误
 }

 // 得到返回的路由器
 ipback = from.sin_addr.s_addr;

 return 1;
}

===============================
函数fill_icmp_data()的源代码
===============================
//这个结构下面将用到
typedef struct _ihdr {
  BYTE i_type;
  BYTE i_code;
  USHORT i_cksum;
  USHORT i_id;
  USHORT i_seq;
  ULONG timestamp; /* 这不是ICMP包的一部分, 只是为了计算时间 */
}IcmpHeader;

void fill_icmp_data(char * icmp_data, int datasize){

  IcmpHeader *icmp_hdr;
  char *datapart;

  icmp_hdr = (IcmpHeader*)icmp_data; 

  icmp_hdr->i_type = ICMP_ECHO;
  icmp_hdr->i_code = 0;
  icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
  icmp_hdr->i_cksum = 0;
  icmp_hdr->i_seq = 0;
 
  datapart = icmp_data + sizeof(IcmpHeader);  //计算数据域的开始地址
  // 初试化数据域
  memset(datapart,'E', datasize - sizeof(IcmpHeader));

}


链接:
-------
我的其它文章,<<透析ICMP协议>>, 和其它文章参见:
http://www.youkuaiyun.com/develop/author/netauthor/bugfree/

联系方式:
-------
 zhangliangsd@hotmail.com

【ICMP】报文抓取分析 文章目录环境1.Win10网络适配器2.Win7网络设置3.防火墙抓取报文1.ping 默认网关2.TRACERT 外网服务器地址(跟踪路由)分析报文1.ICMP2.IP数据分组 环境 1.Win10网络适配器 2.Win7网络设置 3.防火墙 Win7防火墙关闭 抓取报文 1.ping 默认网关 2.TRACERT 外网服务器地址(跟踪路由) 分析报文 1.ICMP 2.IP数据分组 ... 阅读详情

相关推荐

利用ICMP进行路由跟踪

利用ICMP进行路由跟踪 计算机网络作业 vc调试通过

网络诊断工具之—路由追踪tracert命令

路由追踪-tracert Tracert通过递增“生存时间 (TTL)”字段的值将“Internet 控制消息协议 (ICMP) 回响请求”消息发送给目标可确定到达目标的路径。所显示的路径是源主机与目标主机间的路径中的路由器的近侧路由器接口列表。近侧接口是距离路径中的发送主机最近的路由器的接口。 一、tracert命令语法及参数 Tracert命...

weixin_34240657的博客 652

十一种室内定位传感器方案汇总介绍与对比(机器人、物联网领域)

室内定位传感器方案汇总 目录 室内定位传感器方案汇总 1、定位方案概述 1.1、内定位系统有最基本的5种算法: 1.2、常用的室内定位技术主要包括以下几种: 1.3、定位理论 1.4、不同的定位方案对比 2、各种定位方案详细介绍 2.1、单线激光定位 2.2、多线激光定位: 2.3、视觉定位: 2.4、基于射频识别(RFID)技术室内定位 2.4.1、RFID标签(不涉及...

JK-Cool的博客 3万+

setsockopt函数参数详解

函数原型 //函数原型 int setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen); 函数参数解析: s(套接字): 指向一个打开的套接口描述字。 level:(级别): 指定选项代码的类型。  SOL_SOCKET: 基本套接口  IPPROTO_IP: IPv4套接口  IPPROTO_IPV6: IPv6套接口  IPPROTO_TCP: TCP套接口 optname(选项名): 选项名称。 opt

q1449660223的博客 4637

AS7262六通道可见光传感器:从光谱原理到物联网色彩检测实战

光谱检测是嵌入式感知领域的关键技术,其核心原理是通过特定波长的滤光片分离光线并转换为电信号,从而实现对环境光或物体反射光的成分分析。这项技术的价值在于将复杂的光学分析简化为可编程读取的数字信号,极大降低了色彩检测在物联网和智能设备中的应用门槛。在智能农业、工业分拣、环境监测等场景中,精确的光谱数据能够驱动自动化决策,例如评估植物光照条件或识别物料颜色。本文以Adafruit AS7262传感器为例,深入解析其基于硅干涉滤光片的六通道设计,并通过Arduino与Python实战,演示如何快速构建从数据采集到可

weixin_28738173的博客 595

Windows Server远程桌面断开后,PyWinAuto/按键精灵脚本失效?试试这个‘会话保持’的终极配置

本文深入解析Windows Server远程桌面断开后导致PyWinAuto/按键精灵脚本失效的问题,提供会话保持的终极配置方案。通过转换到控制台会话(console模式)和调整组策略,确保自动化程序在断开连接后持续稳定运行,适用于Windows Server各版本。

weixin_28738165的博客 227

网络编程 广播与组播

网络编程 广播与组播

weixin_44240433的博客 210

点云图的学习

一。点云地图拼接 1.1 配置运行环境 首先配置安装opencv3,安装完成后如下图: 然后配置点云图工具pcl,直接使用apt即可安装,安装后如下图: 最后使用点云工具观察点云图: 1.2 原理解析 总的来说由多角度拍摄图片拼接为点云3D图,是通过相机的内参,将像素坐标转化为相机坐标,再通过外参将相机坐标转化为世界坐标系,然后将每张图片的像素绘制填充于同一个世界坐标系下面,形成点云3D图。...

ff_xun的博客 1万+

透析ICMP协议(五): 应用篇路由追踪 (转)

透析ICMP协议(五): 应用篇路由追踪 (转)[@more@]透析ICMP协议(五): 应用篇路由追踪===============================这篇文章出自bugfree/优快云平台: VC6 wind...

ciya3282的博客 90

C#实现自己的远程桌面控制工具

1. 创建一个winform工程并添加RDP客户端COM组件。右击工具箱,然后点击选择项,选中下图所示组件并点击确定。为窗口加载时添加自动连接远程桌面代码。3.调试运行程序,验证远程桌面控制。拖放RDP控件到窗口中。2.编写远程桌面连接代码。

6088

Linux系统安全学习手册

Linux反弹shell Linux系统应急响应 Linux服务器安全加固 Linux下的用户、组和权限 Linux中的gcc Linux中su和sudo的用法和区别 Linux系统python2与python3共存 Linux中grep工具的使用 Linux中环境变量的设置 Linux中常见的150个命令(干货) Linux中编写Shell脚本 LNMP环境搭建Wordpress博客 LAMP环境搭建一个Discuz论坛 Linux运维比较常用的一些脚本 Linux系统中安装软

谢公子的博客 7532

Docker镜像加速全攻略:2026年最新可用源与配置排查指南

容器技术落地过程中,镜像拉取效率直接影响开发与部署体验。Docker Hub作为默认镜像仓库,其服务器位于海外,跨地域网络链路不稳定、匿名拉取频率限制等问题,常导致docker pull长时间卡顿甚至超时。理解registry-mirrors的缓存代理机制,是优化拉取路径的关键:Docker引擎会优先请求配置的镜像加速器,命中缓存即可大幅缩短传输时间。这一机制对热门基础镜像效果显著,也能缓解直连时的网络抖动和限额问题。在实际工程中,无论是Linux环境下的daemon.json配置,还是Docker Des

cuiji1279的博客 317

第十届MathorCup高校数学建模挑战赛-B题:养老服务床位需求预测与运营模式研究

当养老床位数增加时存在的商机,提出了相应的养老服务床位的运营商业模式。就业的可能性,建立多目标规划模型,尽可能同时满足三方面的要求。务床位的需求、制定合理的养老服务床位发展规划,是构建和谐社会、幸福社会。问题一的床位需求与市场类型的分类结果,查找关于国内养老院的相关数据,探。求,又能持续发展养老事业,同时还能促进社会就业的养老服务床位运营的商业。养老服务床位数的增加能够带来的就业方面因素的影响,并对这些因素进行一个。你们的模型及其结论为科学依据,对政府管理部门针对养老床位规划提出合理的。

getusushu的博客 1139

透析ICMP协议(一): 协议原理

透析ICMP协议(一): 协议原理===============================这篇文章原创自bugfree/优快云平台: VC6 Windows XP ICMP简介:--------对于熟悉网络的人来说, ICMP是再熟悉不过了. 它同IP协议一样工作在ISO模型的网络层, 它的全称是: Internet Control Message Protocal.  其在网络中

2394

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

透析ICMP协议(四): 牛刀初试之二 应用篇ping(RAW Socket)

透析ICMP协议(四): 牛刀初试之二 应用篇ping(RAW Socket)===============================这篇文章出自bugfree/优快云平台: VC6 Windows XP 今晚一杯茶水之后, 让我们继续我们的ICMP讨论, 今晚介绍的是用RAW Socket 实现的ping程序.原理简介:--------  用RAW Socket实现的ping可能

2707

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

透析ICMP协议

透析ICMP协议(一): 协议原理 对于熟悉网络的人来说, ICMP是再熟悉不过了. 它同IP协议一样工作在ISO模型的网络层, 它的全称是: Internet Control Message Protocal. 其在网络中的主要作用是: - 主机探测 - 路由维护 - 路由选择 - 流量控制 ...

weixin_34037977的博客 246

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

透析ICMP协议(四): 牛刀初试之二 应用篇ping(RAW Socket) (转)

透析ICMP协议(四): 牛刀初试之二 应用篇ping(RAW Socket) (转)[@more@]透析ICMP协议(四): 牛刀初试之二应用篇ping(RAW Socket)========================...

ciya3282的博客 236
上一篇: 透析ICMP协议(四): 牛刀初试之二 应用篇ping(RAW Socket)
下一篇: 字符串:怎样转换字符串为数字类型?
bugfree
博客等级 码龄24年 1粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值