Tracert 代码

手把手教你用C++实现Tracert路由追踪(附完整代码解析) 本文深入解析了Tracert路由追踪的核心原理,即利用ICMP协议和TTL字段递增机制来探测网络路径。通过C++和原始套接字编程,手把手教你从零构建一个完整的Tracert工具,包括ICMP报文构造、TTL设置、响应解析等关键步骤,并提供了完整的代码实现,帮助你深入理解网络层协议与路由机制。 阅读详情
以前写的Tracert源代码,
相关参考 : http://baike.baidu.com/view/493712.htm
--------------------------------------------------------------------------------------------------
General.h
#include <windows.h>
#ifdef __GENERAL_H__
#define __GENERAL_H__
// CRC Check Sum
extern USHORT ip_checksum(USHORT* buffer, int size);
// Read IP Address from Integer to String
void ReadIPAddress(unsigned long IPAddress);
#endif  // GENERAL_H
 
----------------------------------------------------------------------------------------------------
General.cpp

#include "General.h"
#include <stdio.h>

USHORT ip_checksum(USHORT* buffer, int size)
{
    unsigned long cksum = 0;
   
    // Sum all the words together, adding the final byte if size is odd
    while (size > 1) {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }
    if (size) {
        cksum += *(UCHAR*)buffer;
    }

    // Do a little shuffling
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
   
    // Return the bitwise complement of the resulting mishmash
    return (USHORT)(~cksum);
}

void ReadIPAddress(unsigned long IPAddress)
{
    printf("%d.%d.%d.%d/n", UCHAR(IPAddress),
                                       UCHAR(IPAddress >> 8),
                                       UCHAR(IPAddress >> 16),
                                       UCHAR(IPAddress >> 24));
}

----------------------------------------------------------------------------------------------------------

ICMP.h

#include <windows.h>
#ifndef __ICMP_H__
#define __ICMP_H__

#define ICMP_ECHO 8               // Echo ICMP Packet
#define ICMP_REPLAY 0             // Replay ICMP Packet
#define MAX_DATA_SIZE 1024         
#define ICMP_MIN 8                
#define ICMP_TIMEOUT 11           // Time out ICMP Packet
#define DEFAULT_ICMP_SIZE 44      // The Default ICMP Packet Size

#pragma pack(1)
typedef struct tagICMPHeader
{
    UCHAR type;
    UCHAR code;
    USHORT checkSum;
    USHORT ID;
    USHORT SeqNumber;
}ICMPHeader, *PICMPHeader;
#pragma pack()

#pragma pack(1)
typedef struct tagIPHeader
{
    BYTE h_len:4;
    BYTE version:4;
    BYTE tos;
    USHORT total_len;
    USHORT ID;
    USHORT flags;
    BYTE ttl;
    BYTE proto;
    USHORT checksum;
    ULONG source_ip;
    ULONG dest_ip;
}IPHeader, *PIPHeader;
#pragma pack()

#endif  // ICMP_H

-------------------------------------------------------------------------------------------------------

Tracert.h

#include "ICMP.H"
#include "General.h"
#include <iostream>
using namespace std;

#ifndef __TRACERT_H__
#define __TRACERT_H__

#define TRACERT_DATA_PART_SIZE (DEFAULT_ICMP_SIZE - sizeof(ICMPHeader))
#pragma pack(1)
typedef struct tagTracertPacket
{
    ICMPHeader icmp_header;
    BYTE data_part[TRACERT_DATA_PART_SIZE];
}TracertPacket, *PTracertPacket;
#pragma pack()

class Tracert
{
public:
    Tracert();
    ~Tracert();
    BOOL StartClient();

private:
    void PackTracertPacket(TracertPacket& tracert_packet);
    int UnPackTracertPacketPacket();
    int Configuration();
    int ReceivePacket();
    int SendPacket();
    DWORD InitializeConnection();
    int UnitializeConnection();
    int DecodeTracertPacket(const IPHeader& ip_header, const int recvPacketLen);
    friend USHORT ip_checksum(USHORT* buffer, int size);
    friend void ReadIPAddress(unsigned long IPAddress);

private:
    SOCKET sock;
    sockaddr_in dest;
    sockaddr_in source;
};

#endif  // TRACERT_H

 
-------------------------------------------------------------------------------------------------------
Tracert.cpp

#define  WIN32_LEAN_AND_MEAN
#include <winsock2.h>                     //Need the support of WinSock2
#include <ws2tcpip.h>                     //When setting the level of IPPROTO_IP                                        
#include "Tracert.h"           
#define TRANSFER_OVER 0x05      
static const TCHAR* DEFAULT_ADDRESS = TEXT("220.181.18.155");   // BaiDu Address
static const int TIMEOUT = 1000;                               // 1 second
Tracert::Tracert()
{
    InitializeConnection();
}
 
Tracert::~Tracert()
{
    UnitializeConnection();
}
 
int Tracert::Configuration()
{
    int ttl = TIMEOUT;
 
    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&ttl,
            sizeof(ttl)) == SOCKET_ERROR)
    {
        cout << "Error in Configuration, error code:" <<  GetLastError() << endl;
        return GetLastError();
    }
    memset(&dest, 0, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_addr.s_addr = inet_addr(DEFAULT_ADDRESS);
    return 0;
}
 
int Tracert::SendPacket()
{
    static int livetime = 1;
    int retValue=setsockopt(sock,IPPROTO_IP,IP_TTL,(char *)&livetime,sizeof(int));
    if (retValue < 0)
    {
        cout << "Error in Set Tracert Packet Time, error code" << GetLastError() << endl;
        return GetLastError();
    }
    else
    {
        livetime++;
    }
    TracertPacket tracert_packet;
    PackTracertPacket(tracert_packet);
    retValue = sendto(sock,                          // Socket
                      (const char*)&tracert_packet,  // Buffer
                      sizeof(tracert_packet)
                      0,                             // Flag
                      (const sockaddr*)&dest,        // The Pointer to Socket Address
                      sizeof(dest));                 // Size of Socket Address
    if (retValue < 0)
    {
        cout << "Error in send Packet, error code" << GetLastError() << endl;
        return GetLastError();
    }
    return 0;
}
 
int Tracert::ReceivePacket()
{
    // effetive will be worse?
    IPHeader* recv_buf = (IPHeader*)new TCHAR[MAX_DATA_SIZE];
    if (recv_buf == NULL)
    {
        return GetLastError();
    }
    int fromlen = sizeof(source);
    int retValue = recvfrom(sock,
                            (char*)recv_buf,
                            MAX_DATA_SIZE,
                            0,
                            (sockaddr*)&source,
                            &fromlen);
    if (retValue < 0)
    {
        cout << "Error in receive packet, error code" << GetLastError() << endl;
        return GetLastError();
    }
    else
    {
        // Decode ping packet
        retValue = DecodeTracertPacket(*recv_buf, retValue);
    }
    delete []recv_buf;
    recv_buf = NULL;
    return retValue;
}
 
void Tracert::PackTracertPacket(TracertPacket &tracert_packet)
{
    //static USHORT ID = 1;
    static USHORT SeqNumber = 1;
    tracert_packet.icmp_header.type = ICMP_ECHO;
    tracert_packet.icmp_header.code = 0;
    tracert_packet.icmp_header.checkSum = 0;
    tracert_packet.icmp_header.ID = (USHORT)GetCurrentProcessId();
    tracert_packet.icmp_header.SeqNumber = SeqNumber++;
    memset(tracert_packet.data_part, 'E', TRACERT_DATA_PART_SIZE);
    tracert_packet.icmp_header.checkSum = ip_checksum((USHORT*)&tracert_packet, sizeof(tracert_packet));
}
 
int Tracert::DecodeTracertPacket(const IPHeader &ip_header, const int recvPacketLen)
{
    USHORT ipheader_len = ip_header.h_len * 4;
    if (recvPacketLen < ipheader_len + ICMP_MIN)
    {
        // Packet is too small
        cout << "Receive packet is too small" << endl;
        return -1;
    }
   
    TracertPacket *tracertpacket = (TracertPacket*)((char*)&ip_header + ipheader_len);
    if (tracertpacket == NULL)
    {
        cout << "ICMP Header is NULL" << endl;
        return -1;
    }
 
    if (tracertpacket->icmp_header.type == ICMP_TIMEOUT && tracertpacket->icmp_header.code == 0)
    {
        //cout << "Reply Packet" << endl;
        //cout << "time:" << int (GetTickCount() - pingpacket->dwTime) << endl;
        cout << "Route Address:";
        ReadIPAddress(ip_header.source_ip);
    }
   
    if(tracertpacket->icmp_header.type==ICMP_REPLAY &&
       tracertpacket->icmp_header.ID==GetCurrentProcessId())
    {
        //printf("%2d:        %-15s       %4dms/n",icmpcount++,
        //       inet_ntoa(from->sin_addr),tick-cStartTickCount);
        cout << "Route Address:";
        ReadIPAddress(ip_header.source_ip);
        printf("Trace complete!/n");
        return TRANSFER_OVER;
    }
    return 0;
}
 
BOOL Tracert::StartClient()
{
    int flag = 0;
    while(true)
    {
        if (SendPacket())
        {
            return FALSE;
        }
        flag = ReceivePacket();
        if (flag == TRANSFER_OVER)
        {
            return TRUE;
        }
        else if (flag)
        {
            return FALSE;
        }
        Sleep(1000);
    }
    return TRUE;
}
 
DWORD Tracert::InitializeConnection()
{
    cout << "+Initialize Connection!" << endl;
    WSAData wsaData;
    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
    {
        cout << "Startup error!" << endl;
        return GetLastError();
    }
    sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (sock < 0)
    {
        cout << "Create socket error!" << endl;
        return GetLastError();
    }
    if (Configuration())
    {
        return GetLastError();
    }
    cout << "-Initialize Connection!" << endl;
    return 0;
}
 
int Tracert::UnitializeConnection()
{
    WSACleanup();
    closesocket(sock);
    cout << "Unitialize Connection!" << endl;
    return 0;
}
 
int Tracert::UnPackTracertPacketPacket()
{
    return 0;
}
-------------------------------------------------------------------------------------------------------------
main.cpp
 
#include "Tracert.h"
int main()
{
    Tracert tracert_Program;
    tracert_Program.StartClient();
    return 0;
}
 
Windows下用Dev C++实现局域网主机探测(Ping+Tracert完整代码解析) 本文详细解析了如何在Windows环境下使用Dev C++和原生Socket编程,通过直接操作ICMP协议实现局域网主机探测。文章提供了Ping扫描与Tracert路由追踪的完整C++代码实现,深入讲解了ICMP报文构造、校验和计算、原始套接字使用及结果解析,是学习网络编程和协议底层原理的实战指南。 阅读详情

相关推荐

Tracert命令解析 - 目标跟踪

Tracert(Trace Route)是一个常用的网络诊断工具,用于确定数据包从源主机到目标主机的路径。Tracert(Trace Route)是一种常用的网络诊断工具,用于确定数据包从源主机到目标主机的路径。Tracert命令通过发送一系列的ICMP数据包,利用数据包的TTL(Time to Live)字段来确定路径上的路由器。Tracert命令通过发送一系列的ICMP数据包,利用数据包的TTL(Time to Live)字段来确定路径上的路由器。是要跟踪的目标主机的IP地址或域名。

TuoGroovy的博客 1227

android+tracert命令详解,tracert 命令详解(示例代码)

tracert 命令详解How to Use the TRACERT UtilityThe TRACERT diagnostic utility determines the route to a destination by sending Internet Control Message Protocol (ICMP) echo packets to the destination. In t...

weixin_31859675的博客 1301

使用Tracert命令在Windows 11中进行编程

Tracert命令是Windows操作系统中的一个网络工具,用于跟踪数据包在网络上的传输路径。在Windows 11中,您可以使用Tracert命令通过编程方式自动执行网络跟踪操作。本文将向您展示如何使用Tracert命令编程地在Windows 11上进行网络跟踪操作。在Windows 11中,您可以使用Python编程语言来执行Tracert命令。模块,您可以在Windows 11上编程地执行Tracert命令进行网络跟踪操作。在命令行中,Tracert命令的语法是。函数执行了Tracert命令,并将。

HackWhisper的博客 369

1小时打造可视化tracert工具:低代码开发实战

网络诊断工具是运维和开发的刚需,但传统tracert命令的黑白输出对新手不够友好。最近我用低代码方式快速实现了一个可视化版本,将核心功能浓缩到1小时开发流程中,分享关键步骤和避坑经验。:注意Windows和Linux的tracert/traceroute参数差异,建议统一超时设置和最大跳数限制。对于需要快速验证产品创意的场景,这种从开发到部署的短路径确实能节省大量时间。特别是地图API调用这类需要外网访问的功能,平台已经预置了代理支持,省去申请备案域名的麻烦。热力色阶按延迟百分比动态调整。

GreyWolf12的博客 792

网络协议 -- ICMP协议(3)Tracert程序

Tracert是windows系统提供的一个工具,使用该程序可以让我们看到IP数据报从一台主机到另一台主机所经过的路由器。Linux系统也提供了类似的工具,叫traceroute,功能和Tracert一样。 一、 Tracert原理 在介绍Tracert的原理之前,需要先弄清楚IP首部TTL字段的含义,IP报文每经过一个路由器,路由器都会将该IP报文首部的TTL字段减1, 当路由器收到一

while(1) { smile(); } 12万+

Ansys HFSS 中的同轴电缆仿真

准确模拟它们的行为对于确保 RF 系统的最佳性能至关重要。在本博客中,我们将介绍在 HFSS 中设置同轴电缆仿真并绘制插入损耗、回波损耗和电场分布的过程。将波端口分配给同轴线的两端以激励模型,并定义了从 1 GHz 到 20 GHz 的频率扫描以评估其宽带性能。铜分配给内部导体,铝分配给外部导体。介电区域使用 PTFE 定义,其相对介电常数为 2.1,损耗角正切为 0.00022。仿真完成后,结果用于绘制整个频率范围内的回波损耗和插入损耗。此外,电介质内的电场分布也被绘制和动画化。

jkh920184196的博客 1907

c语言自动追踪程序,tracert跟踪路由C语言源代码

#define WIN32_LEAN_AND_MEAN#include //使用原始套接字需要WinSock2的支持#include //进行IPPROTO_IP级别设置时用到#include #include #define ICMP_ECHO 8 //发送Ping请...

weixin_29958373的博客 1529

BES (恒玄)HFP通话笔记

1.audio_developer 调试:SDK 需要打开某个算法,需要原厂打开对应宏定义编译出新的SDK,只要涉及到lib库里的功能都需要原厂手动修改编译。开发商和原厂FAE做起来都会比较累。如果没有原厂支持根本没法做,很少文档,SDK也很多问题,没法开箱即用如果要支持audio_developer上位机调试,还需改代码,如果对整个原理不清楚就没法做,没文档只能啃代码调试工具设计的也有待加强,串口通讯调试对耳机这类产品非常麻烦,本来板子就不大,还要焊接一堆线,调试还要拖着串口线。

飞天鱼 686

二、Tracert 与 Ping 程序设计与实现

【代码】二、Tracert 与 Ping 程序设计与实现。

wushang798的博客 2060

局部,全局(外部),static等变量详解

首先,必须明白一个程序是包含若干个源文件,每个源文件又是包含若干个函数,每个源文件、函数中又定义了若干个变量。但是每个变量都有自己的作用范围,也就是自己的作用域。只有在作用域内才可以访问变量。 变量的有效范围称为变量的作用域( scope)。归纳起来,变量有4种不同的作用域:文件作用域( file scope)、函数作用域( function scope)、块作用域(block sc...

归根结底不优秀的博客 1322

告别迷茫!手把手教你用Synopsys VC USB VIP搭建验证平台(附UVM分层序列实战解析)

本文详细介绍了如何使用Synopsys VC USB VIP搭建验证平台,并深入解析UVM分层序列的实战应用。通过Step-by-Step的操作指南和关键配置示例,帮助验证工程师高效集成USB VIP,掌握从环境搭建到测试用例开发的全套技能,特别适合处理复杂协议验证的挑战。

weixin_42520573的博客 553

tracert跟踪路由C语言源代码

#define WIN32_LEAN_AND_MEAN #include //使用原始套接字需要WinSock2的支持 #include //进行IPPROTO_IP级别设置时用到 #inclu

5617

手把手教你用微信小程序实现智能硬件音视频通话(含Linux/RTOS适配)

本文详细介绍了如何利用微信小程序硬件框架(WMPF)和音视频SDK,在智能硬件(包括Linux与RTOS设备)上实现音视频通话功能。文章从架构设计、设备端SDK集成、小程序VOIP插件开发到跨平台调试与性能优化,提供了全链路实战指南,帮助开发者打通微信小程序与嵌入式设备间的实时音视频通信。

ooo22的博客 329

Tracert程序

在PingExample程序的基础上,完成一个Tracert程序 改写的技术思路: 每个路由器收到ICMP报文都会将TTL减一再发送到下一个路由,当TTL减少到0时,将值返回源IP地址。(TTL需小于30) 改写的核心源代码: private void buttonPing_Click(object sender, EventArgs e) { this.listBox1.Items...

qq_44586215的博客 706

基于 STM32 的乒乓球发球机控制系统设计与实现

乒乓球发球机是一种能够按照预设参数自动、连续发出乒乓球的训练设备。本系统以 STM32F103C8T6 为主控核心,通过控制实现球速调节、实现落点与旋转方向控制、实现出球节奏控制,并配合 OLED 显示与按键人机交互,实现速度、频率、落点、旋转四大参数的可调发球训练。

weixin_42300449的博客 210

基于电能质量治理的场景实例:统一电能质量调节器(UPQC)与并网逆变器集成

本文通过Simulink平台,详细演示了统一电能质量调节器(UPQC)与并网逆变器的集成系统建模与仿真过程。主要内容包括:1)系统架构设计,包含光伏并网系统、非线性负载和电压扰动源;2)UPQC主电路设计,包括串联/并联单元拓扑和控制策略实现;3)与并网逆变器的能量交互与协同控制逻辑;4)典型电能质量问题的仿真测试场景。结果表明,该集成系统能有效治理电压暂降(维持负载电压380V±2%)和电流谐波(电网THD<3%),直流母线电压稳定在800V±5V。该系统为应对复杂电能质量问题提供了"电压

xiaoheshang_123的博客 310

计算机网络课程设计-Tracert 与 Ping 程序设计与实现

本实验为计算机网络课程设计内容,基本上所有代码都是根据指导书给的附录写出来的。有些实验需要实现图形界面,但是出于期末考试压力,我所有实验均是在控制台输入输出的,没有花额外时间去学习qt了,有精力的同学可以自学一下qt实现简单的图形界面。同时,该博客内容为部分报告内容,仅为大家提供参考,请勿直接抄袭。另外,本次实验所用平台是dev c++5.11。

qq_63306482的博客 2407

FPGA原型验证(八):SoC设计适配与实现策略

时钟门控在SoC设计中很常见,应该小心处理门控时钟,以成功地在FPGA上原型化SoC设计。现代FPGA综合工具在正确约束的情况下,可以自动处理大多数门控时钟。通过遵循本章中的指导方针,即使具有复杂时钟门控的SoC设计也可以得到处理,并成功地在FPGA上进行原型化。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 477

java tracert_Java模拟Tracert和ping命令实现跃点追踪

1. Tracert(跟踪路由)用于确定 IP数据包访问目标所采取的路径。Tracert 命令使用用 IP 生存时间 (TTL) 字段和 ICMP错误消息来确定从一个Host到网络上其他主机的Routertracert命令能够显示你的数据包在网络上进行传输时经历的一个个大大小小的ISP的路由器。2.PING(Packet Internet Groper),即因特网包探索器。可以用来测试网络连接...

weixin_35705450的博客 2169

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

计算机网络课程设计之Tracert与Ping程序设计与实现

Tracert Ping Windows

RongLin02的博客 8289

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java tracert_Java调用cmd下的tracert(路由跟踪)命令

importjava.io.BufferedReader;importjava.io.File;importjava.io.FileReader;importjava.io.FileWriter;importjava.io.IOException;importjava.io.InputStreamReader;importjava.util.ArrayList;importjava.util.Li...

weixin_33093437的博客 488

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Python 实现Tracert追踪TTL值

Tracert 命令跟踪路由原理是IP路由每经过一个路由节点TTL值会减一,假设TTL值=0时数据包还没有到达目标主机,那么该路由则会回复给目标主机一个数据包不可达,由此我们就可以获取到目标主机的IP地址,如下我们通过scapy构造一个路由追踪工具并实现一次追踪。

微软技术分享 7202

Perl Tracert 实现方法(Net::Traceroute::PurePerl)

分析了一下Tracert的实现脚本,自己思考了一下具体如何实现。 其中在Linux下应该叫traceroute。 这个模块相对介绍的比较模糊,CPAN上出的都是一些比较模糊的介绍,让人比较纠结。 只能对参数进行测试,测出来的。 先看下案例把: #!/usr/bin/perl ...

chiqu8683的博客 152

Java实现tracert、ping执行打印

Java实现tracert、ping命令执行

m0_46252893的博客 843

008B-tracert,tracertroute,icmp 重定向

ICMP报文: ICMP重定向:在同一个局域网中,网关和数据的下一跳在同一个网段中,从该接口收到的数据要从该接再发送回下去 008A-ICMP 表1 ICMP消息类型代码对应表 类型Type 代码Code 描述 0 0 回显应答(ping应答) 3 0 网络不可达 3 1 主机不可达 3 2 协议不可达 3 3 端口不可达 3 4 需要进行分片但设置不分片比特 ...

csdn_immortal的博客 455
上一篇: Ping的代码
下一篇: SVN打分支操作
enjoyeclipse
博客等级 码龄19年 5粉丝 22原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值