Tracert 与 Ping 程序设计与实现(2024)

1.题目描述

了解 Tracert 程序的实现原理,并调试通过。然后参考 Tracert 程序和计算机网络教材 4.4.2 节, 计算机网络 课程设计指导书 2 编写一个 Ping 程序,并能测试本局域网的所有机器是否在线,运行界面如下图所示的 QuickPing 程序。


2.程序Demo

aaf753f838634837989a1fc8fbb5e2bf.png


3.参考代码

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#include "sstream"using namespace std;
#pragma comment(lib, "Ws2_32.lib")
//IP 报头
typedef struct {unsigned char hdr_len: 4;       //4 位头部长度unsigned char version: 4;       //4 位版本号unsigned char tos;              //8 位服务类型unsigned short total_len;       //16位总长度unsigned short identifier;      //16位标识符unsigned short frag_and_flags;  //3 位标志加 13 位片偏移unsigned char ttl;              //8 位生存时间unsigned char protocol;         //8 位上层协议号unsigned short checksum;        //16位校验和unsigned long sourceIP;         //32位源 IP 地址unsigned long destIP;           //32位目的 IP 地址
} IP_HEADER;
//ICMP 报头
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; //往返时间in_addr dwIPaddr; //返回报文的 IP 地址
} DECODE_RESULT;//计算网际校验和函数
USHORT checksum(USHORT *pBuf, int iSize) {unsigned long cksum = 0;while (iSize > 1) {cksum += *pBuf++;iSize -= sizeof(USHORT);}if (iSize) {cksum += *(UCHAR *) pBuf;}cksum = (cksum >> 16) + (cksum & 0xffff);cksum += (cksum >> 16);return (USHORT) (~cksum);
}//对数据包进行解码
BOOL DecodeIcmpResponse(char *pBuf, int iPacketSize, DECODE_RESULT &DecodeResult, BYTE ICMP_ECHO_REPLY, BYTE ICMP_TIMEOUT) {//检查数据报大小的合法性IP_HEADER *pIpHdr = (IP_HEADER *) pBuf;int iIpHdrLen = pIpHdr->hdr_len * 4;if (iPacketSize < (int) (iIpHdrLen + sizeof(ICMP_HEADER))) return FALSE;//根据 ICMP 报文类型提取 ID 字段和序列号字段ICMP_HEADER *pIcmpHdr = (ICMP_HEADER *) (pBuf + iIpHdrLen);USHORT usID, usSquNo;if (pIcmpHdr->type == ICMP_ECHO_REPLY) //ICMP 回显应答报文{usID = pIcmpHdr->id; //报文 IDusSquNo = pIcmpHdr->seq; //报文序列号} else if (pIcmpHdr->type == ICMP_TIMEOUT)//ICMP 超时差错报文{char *pInnerIpHdr = pBuf + iIpHdrLen + sizeof(ICMP_HEADER); //载荷中的 IP 头int iInnerIPHdrLen = ((IP_HEADER *) pInnerIpHdr)->hdr_len * 4; //载荷中的 IP 头长ICMP_HEADER *pInnerIcmpHdr = (ICMP_HEADER *) (pInnerIpHdr + iInnerIPHdrLen);//载荷中的 ICMP头usID = pInnerIcmpHdr->id; //报文 IDusSquNo = pInnerIcmpHdr->seq; //序列号} else {return false;}//检查 ID 和序列号以确定收到期待数据报if (usID != (USHORT) GetCurrentProcessId() || usSquNo != DecodeResult.usSeqNo) {return false;}//记录 IP 地址并计算往返时间DecodeResult.dwIPaddr.s_addr = pIpHdr->sourceIP;DecodeResult.dwRoundTripTime = GetTickCount() - DecodeResult.dwRoundTripTime;//处理正确收到的 ICMP 数据报if (pIcmpHdr->type == ICMP_ECHO_REPLY || pIcmpHdr->type == ICMP_TIMEOUT) {//输出往返时间信息if (DecodeResult.dwRoundTripTime)cout << " " << DecodeResult.dwRoundTripTime << "ms" << flush;elsecout << " " << "<1ms" << flush;}return true;
}// 数字转String
string num2str(int &num) {string str;stringstream ss;ss << num;ss >> str;return str;
}//提取IP
string GetIP(string ip) {char separator = '.';int i = 0, count = 3;// Temporary string used to split the string.string s;while (ip[i] != '\0') {if (ip[i] != separator) {s += ip[i];} else {s += ip[i];count--;}if (count == 0) {break;}i++;}return s;
}int main() {cout<<" *======Tracert 与 Ping 程序设计与实现======* "<<endl;//定义=====================================================================int iTimeout = 10;                    //超时时间const int DEF_MAX_HOP = 1;             //检查次数BOOLEAN Show_All = false;              //是否输出所有信息string Scan_ip;//ICMP 类型字段const BYTE ICMP_ECHO_REQUEST = 8;      //请求回显const BYTE ICMP_ECHO_REPLY = 0;        //回显应答const BYTE ICMP_TIMEOUT = 11;          //传输超时//其他常量定义const int DEF_ICMP_DATA_SIZE = 32;     //ICMP 报文默认数据字段长度const int MAX_ICMP_PACKET_SIZE = 1024; //ICMP 报文最大长度(包括报头)const DWORD DEF_ICMP_TIMEOUT = 100;    //回显应答超时时间int OnlineNum = 0;//=======================================================================cout << "请输入路由器IP:";cin >> Scan_ip;//初始化 Windows sockets 网络环境WSADATA wsa;WSAStartup(MAKEWORD(2, 2), &wsa);const char *IpAddress;string IpA;cout <<endl<<" 开始扫描:"<<endl;cout << "----------------------------------------------------------------" << endl;cout << "     耗时         机器IP           序号           状态          |" << endl;cout << "----------------------------------------------------------------" << endl;for (int i = 1; i < 254; i++) {IpA = GetIP(Scan_ip)+ num2str(i);IpAddress = IpA.c_str();// cout << IpA << endl;//得到 IP 地址u_long ulDestIP = inet_addr(IpAddress);//转换不成功时按域名解析if (ulDestIP == INADDR_NONE) {hostent *pHostent = gethostbyname(IpAddress);if (pHostent) {ulDestIP = (*(in_addr *) pHostent->h_addr).s_addr;} else {cout << "输入的 IP 地址或域名无效!" << endl;WSACleanup();return 0;}}//填充目地端 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, 0, WSA_FLAG_OVERLAPPED);//接收超时setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char *) &iTimeout, sizeof(iTimeout));//发送超时setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char *) &iTimeout, sizeof(iTimeout));//填充 ICMP 报文中每次发送时不变的字段char IcmpSendBuf[sizeof(ICMP_HEADER) + DEF_ICMP_DATA_SIZE];//发送缓冲区memset(IcmpSendBuf, 0, sizeof(IcmpSendBuf)); //初始化发送缓冲区char IcmpRecvBuf[MAX_ICMP_PACKET_SIZE]; //接收缓冲区memset(IcmpRecvBuf, 0, sizeof(IcmpRecvBuf)); //初始化接收缓冲区ICMP_HEADER *pIcmpHeader = (ICMP_HEADER *) IcmpSendBuf;pIcmpHeader->type = ICMP_ECHO_REQUEST; //类型为请求回显pIcmpHeader->code = 0; //代码字段为 0pIcmpHeader->id = (USHORT) GetCurrentProcessId(); //ID 字段为当前进程号memset(IcmpSendBuf + sizeof(ICMP_HEADER), 'E', DEF_ICMP_DATA_SIZE);//数据字段USHORT usSeqNo = 0; //ICMP 报文序列号int iTTL = 1; //TTL 初始值为 1BOOL bReachDestHost = FALSE; //循环退出标志int iMaxHot = DEF_MAX_HOP; //循环的最大次数DECODE_RESULT DecodeResult; //传递给报文解码函数的结构化参数while (!bReachDestHost && iMaxHot--) {//设置 IP 报头的 TTL 字段setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char *) &iTTL, sizeof(iTTL));//  cout << iTTL << flush; //输出当前序号//填充 ICMP 报文中每次发送变化的字段((ICMP_HEADER *) IcmpSendBuf)->cksum = 0; //校验和先置为 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(); //当前时间//发送 TCP 回显请求信息sendto(sockRaw, IcmpSendBuf, sizeof(IcmpSendBuf), 0, (sockaddr *) &destSockAddr, sizeof(destSockAddr));//接收 ICMP 差错报文并进行解析处理sockaddr_in from; //对端 socket 地址int iFromLen = sizeof(from); //地址结构大小int iReadDataLen; //接收数据长度while (true) {//接收数据iReadDataLen = recvfrom(sockRaw, IcmpRecvBuf, MAX_ICMP_PACKET_SIZE, 0, (sockaddr *) &from, &iFromLen);if (iReadDataLen != SOCKET_ERROR)//有数据到达{//对数据包进行解码if (DecodeIcmpResponse(IcmpRecvBuf, iReadDataLen, DecodeResult, ICMP_ECHO_REPLY, ICMP_TIMEOUT)) {//到达目的地,退出循环if (DecodeResult.dwIPaddr.s_addr == destSockAddr.sin_addr.s_addr)bReachDestHost = true;break;}} else if (WSAGetLastError() == WSAETIMEDOUT & Show_All) //接收超时,输出*号{cout << '\t' << "请求超时 " << DEF_MAX_HOP - iMaxHot << "次" << endl;break;} else {break;}}iTTL++; //递增 TTL 值}if (WSAGetLastError() != WSAETIMEDOUT) {cout << "         " << IpA << "            " << i << "            在线" << endl;OnlineNum++;if (Show_All)cout << "================================================================" << endl;} else if (WSAGetLastError() == WSAETIMEDOUT & Show_All) {cout << "         " << IpA << "             " << i << "           离线" << endl;cout << "================================================================" << endl;}}cout << "================================================================" << endl;cout << endl << "检测到 " << OnlineNum << " 台设备在线" << endl<< endl;system("pause");WSACleanup();return 0;
}

4.导入ws2_32库到Clion :

导入ws2_32库到Clion项目-CSDN博客

 2024 HNUST计算机网络课程设计-(ᕑᗢᓫ∗)˒芒果酱-参考文章

(代码可以参考,૮₍ ˃ ⤙ ˂ ₎ა 但同学们要认真编写哦)
-------------------------------------------------------------------------
1、网络聊天程序的设计与实现
C++ Socket 多线程 网络聊天室 支持用户端双向交流(2023)-CSDN博客
2、Tracert 与 Ping 程序设计与实现
Tracert 与 Ping 程序设计与实现(2024)-CSDN博客
3、滑动窗口协议仿真
滑动窗口协议仿真(2024)-CSDN博客
4、OSPF 路由协议原型系统设计与实现
OSPF 路由协议原型系统设计与实现-CSDN博客
5、基于 IP 多播的网络会议程序
基于 IP 多播的网络会议程序(2024)-CSDN博客
6、编程模拟 NAT 网络地址转换
编程模拟 NAT 网络地址转换(2024)-CSDN博客
7、网络嗅探器的设计与实现
网络嗅探器的设计与实现(2024)-转载-CSDN博客
8、网络报文分析程序的设计与实现
网络报文分析程序的设计与实现(2024)-CSDN博客
9、简单 Web Server 程序的设计与实现
简单 Web Server 程序的设计与实现 (2024)-CSDN博客
10、路由器查表过程模拟

计算机网络 - 路由器查表过程模拟 C++(2024)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/604953.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【docker】centos 使用 Nexus Repository 搭建私有仓库

Nexus Repository 是一种流行的软件仓库管理工具&#xff0c;它可以帮助您搭建私有仓库&#xff0c;以便在内部网络或私有云环境中存储、管理和分发各种软件包和组件。 它常被用于搭建Maven的镜像仓库。本文演示如何用Nexus Repository搭建docker 私有仓库。 使用Nexus Repos…

毕业设计:基于机器学习xgboost lgbm adaboost 的空气质量预测pm2.5‘, ‘so2‘, ‘no2‘ 完整代码数据-可直接运行

项目详细视频讲解介绍: 基于机器学习xgboost lgbm adaboost 的空气质量预测-完整代码数据可直接运行_哔哩哔哩_bilibili 数据展示: 运行结果展示: 项目代码: from sklearn import preprocessing import random from sklearn.model_selection import train_test_split fr…

《GreenPlum系列》GreenPlum详细入门教程01-GreenPlum介绍

文章目录 第一章 GreenPlum介绍1.MPP架构介绍2.GreenPlum介绍3.GreenPlum数据库架构4.GreenPlum数据库优缺点 GreenPlum&#xff1a;https://cn.greenplum.org/ 第一章 GreenPlum介绍 1.MPP架构介绍 MPP是Massively Parallel Processing的缩写&#xff0c;也就是大规模并行处…

GEE数据集——Cloud Score+ S2_HARMONIZED数据集

简介 Cloud Score 是一种用于中高分辨率光学卫星图像的质量评估&#xff08;QA&#xff09;处理器。Cloud Score S2_HARMONIZED数据集是由统一的哨兵-2 L1C数据集制作的&#xff0c;Cloud Score的输出可用于识别相对清晰的像素&#xff0c;并有效去除L1C&#xff08;大气顶部&…

GPDB - 高可用 - 流复制状态

GPDB - 高可用 - 流复制状态 GPDB的高可用基于流复制&#xff0c;通过FTS进行自动故障切换。自动故障切换需要根据primary-mirror流复制的各种状态进行判断。本节就聊聊primary-mirror流复制的各种状态。同样适用于PgSQL 1、WalSndState typedef enum WalSndState {WALSNDSTATE…

04-微服务-Nacos

Nacos注册中心 国内公司一般都推崇阿里巴巴的技术&#xff0c;比如注册中心&#xff0c;SpringCloudAlibaba也推出了一个名为Nacos的注册中心。 1.1.认识和安装Nacos Nacos是阿里巴巴的产品&#xff0c;现在是SpringCloud中的一个组件。相比Eureka功能更加丰富&#xff0c;在…

MySQL-存储引擎

简介&#xff1a;存储引擎是存储数据&#xff0c;建立索引&#xff0c;更新/查询数据等技术的实现方式。存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c; (同一个数据库的不同表可以选择不同的存储引擎) 所以存储引擎也可被称为表类型。 我们输入 SHOW CREATE TAB…

Halcon机器视觉和运动控制软件通用框架,24年1月最新版新增UI设计器,插件式开发,开箱即用 仅供学习!

24年1月更新 下载点我 此版本已经添加ui设计器。具体功能如上所示&#xff0c;可以自定义变量&#xff0c;写c#脚本&#xff0c;自定义流程&#xff0c;包含了halcon脚本和封装的算子&#xff0c;可自定义ui&#xff0c;通过插件形式开发很方便拓展自己的功能。 ui设计器

消息队列-RocketMQ-概览与搭建

RocketMQ 领域模型 RockeMQ整体结构预览 RocketMQ 中的一些概念 Topic&#xff1a;主题&#xff0c;可以理解为类别、分类的概念 MessageQueue&#xff1a;消息队列&#xff0c;存储数据的一个容器&#xff08;队列索引数据&#xff09;&#xff0c;默认每个 Topic 下有 4 个队…

AI担任编程导师:生成式AI如何翻江倒海改变开发世界

生成式 AI 如何重塑开发流程和开发工具&#xff1f; 在21世纪的舞台上&#xff0c;AI作为技术明星&#xff0c;一直以其潜力无穷的表现吸引着我们的目光。而其中&#xff0c;一名角色&#xff0c;响亮的名字叫做生成式AI&#xff0c;正在以翩翩起舞的姿态&#xff0c;改变着我…

华为mstp、vrrp、ospf、isis、bgp等综合一起排错

最终实现左边私网和右边私网全部ping通 SW1 vlan batch 12 34 stp region-configuration //mstp配置 region-name test instance 12 vlan 12 instance 34 vlan 34 active region-configuration interface GigabitEthernet0/0/3 port link-type trunk port trunk allow-pass …

Windows11 - Ubuntu 双系统及 ROS、ROS2 安装

系列文章目录 前言 一、Windows11 - Ubuntu 双系统安装 硬件信息&#xff1a; 设备名称 DESKTOP-B62D6KE 处理器 13th Gen Intel(R) Core(TM) i5-13500H 2.60 GHz 机带 RAM 40.0 GB (39.8 GB 可用) 设备 ID 7673EF86-8370-41D0-8831-84926668C05A 产品 ID 00331-10000-0000…

(低级错误)IDEA/Goland报错连接数据库失败:URL错误和权限问题。

前言 做毕设ing&#xff0c;使用Goland自带的数据库工具连接服务器的数据库。报错 错误: Malformed database URL, failed to parse the main URL sections. (view)服务器是华为云&#xff0c;使用宝塔面板。数据库版本5.6.50。 排查过程 鉴于Goland报错报的狗屁不是&#…

【MySQL】视图,外连接内连接子查询简单介绍及面试笔试案例题

目录 一 视图 1.1视图是什么 1.2 创建视图 1.3 查看视图(两种) 1.4 修改视图(两种) 1.5 删除视图 二 外连接&内连接&子查询介绍 2.1 外连接 2.2 内连接 2.3 子查询 三 外连接&内连接&子查询案例 3.1 了解表结构与数据 3.2 案例题目 四 思维导图…

【算法Hot100系列】合并 K 个升序链表

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

不同像平面坐标系下的Brown畸变系数互转

不同像平面坐标系下Brown畸变系数转换 记 u , v u,v u,v为像素为单位的坐标&#xff0c;f为焦距&#xff0c;单位也是像素。 记 x , y x,y x,y为理想坐标。本文推导两种情况下的Brown畸变系数转换关系&#xff1a; 相同坐标系定义、不同的坐标单位&#xff08;像素坐标与归一…

RocketMQ源码 事务消息 TransactionalMessage 源码分析

前言 原理&#xff1a;使用普通消息和订单事务无法保证一致的原因&#xff0c;本质上是由于普通消息无法像单机数据库事务一样&#xff0c;具备提交、回滚和统一协调的能力。 而基于 RocketMQ 的分布式事务消息功能&#xff0c;在普通消息基础上&#xff0c;支持二阶段的提交能…

像专家一样使用TypeScript映射类型

掌握TypeScript的映射类型&#xff0c;了解TypeScript内置的实用类型是如何工作的。 您是否使用过Partial、Required、Readonly和Pick实用程序类型? 你知道他们内部是怎么运作的吗? 如果您想彻底掌握它们并创建自己的实用程序类型&#xff0c;那么不要错过本文所涵盖的内容。…

LabVIEW开发自动读取指针式仪表测试系统

LabVIEW开发自动读取指针式仪表测试系统 在工业领域&#xff0c;尤其是煤矿、变电站和集气站等环境中&#xff0c;指针式仪表因其简单的结构、抗干扰能力强以及能适应高温高压等恶劣环境条件而被广泛应用于设备运行状态监视。然而&#xff0c;传统的人工读表方式不仅成本高昂&…

【AIGC工具】我找到了使用大模型问答的最短路径!

大家好&#xff0c;我是豆小匠~ 好久没介绍提高效率的工具啦&#xff0c;这次来介绍一个UTools的骚操作&#xff0c;可以极速打开LLM进行提问&#xff01; 完成后的效果是&#xff1a; 快捷键调出输入框&#xff1b;2. 输入问题&#xff1b;3. 选择模型&#xff1b;4. 回车提…