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

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博客
相关文章:
Tracert 与 Ping 程序设计与实现(2024)
1.题目描述 了解 Tracert 程序的实现原理,并调试通过。然后参考 Tracert 程序和计算机网络教材 4.4.2 节, 计算机网络 课程设计指导书 2 编写一个 Ping 程序,并能测试本局域网的所有机器是否在线,运行界面如下图所示的 QuickPing …...
浅谈接口自动化测试
前言 自动化测试,算是近几年比较火热的一个话题,当然,更是软件测试未来的一个发展趋势。未来,功能测试等非核心的测试工作,都将被外包。 想要在软件测试这个行业继续前行,就必须拥有核心竞争力࿰…...
Hyperledger Fabric 核心概念与组件
要理解超级账本 Fabric 的设计,首先要掌握其最基本的核心概念与组件,如节点、交易、排序、共识、通道等。 弄清楚这些核心组件的功能,就可以准确把握 Fabric 的底层运行原理,深入理解其在架构上的设计初衷。知其然,进…...
【C语言题解】 | 101. 对称二叉树
101. 对称二叉树 101. 对称二叉树代码 101. 对称二叉树 这个题目要求判断该二叉树是否为对称二叉树,此题与上一题,即 100. 相同的树 这个题有异曲同工之妙,故此题可借鉴上题。 我们先传入需要判断二叉树的根节点,通过isSameTree()…...
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机掉线自动重连(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机掉线自动重连(C#) Baumer工业相机Baumer工业相机的掉线自动重连的技术背景通过PnP事件函数检查Baumer工业相机是否掉线在NEOAPI SDK里实现相机掉线重连方法:工业相机掉线重连测试演示图…...
[Vulnhub靶机] DriftingBlues: 5
[Vulnhub靶机] DriftingBlues: 5靶机渗透思路及方法(个人分享) 靶机下载地址: https://download.vulnhub.com/driftingblues/driftingblues5_vh.ova 靶机地址:192.168.67.24 攻击机地址:192.168.67.3 一、信息收集 …...
26 数字验证
效果演示 实现了一个简单的数字密码输入表单,用户需要输入一个4位数字密码来验证身份。表单包含一个标题、描述、输入字段、两个按钮和一个关闭按钮。输入字段是一个4位数字密码,用户需要在每个输入框中输入数字来输入密码。两个按钮分别是“验证”和“清…...
echarts - xAxis.type设置time时该如何使用formatter的分级模板
echarts 文档中描述了x轴的多种类型 一、type: ‘value’ ‘value’ 数值轴,适用于连续数据。 此时x轴数据是从零开始,有数据大小的区分。 【注意】 因为xAxis.data是为category服务的,所以xAxis.data里面设置的数据无效。 二、type: ‘ca…...
【代码随想录】刷题笔记Day47
前言 又过了个愉快的周末~大组会终于不用开了,理论上已经可以回家了!但是我多留学校几天吧,回家实在太无聊了,也没太多学习的氛围 198. 打家劫舍 - 力扣(LeetCode) dp[i]含义 考虑下标i(包括…...
6.1 截图工具HyperSnap6简介
图片是组成多媒体作品的基本元素之一,利用图片可以增强多媒体作品的亲和力和说说服力。截取图片最简单的方法是直接按下键盘上的“PrintScreen”键截取整个屏幕或按下“AltPrintScreen”组合键截取当前活动窗口,然后在画笔或者其它的图片处理软件中进行剪…...
stable diffusion 人物高级提示词(二)衣物、身材
一、衣服大类 英文中文Shirt衬衫Blouse女式衬衫Dress连衣裙Skirt裙子Pants裤子Jeans牛仔裤Swimsuit泳衣Underwear内衣Bra文胸Panties内裤Stockings长筒袜Shoes鞋子Socks袜子 二、细分分类 dress 是连衣裙: 英文解释Formal Dress正式礼服,通常用于正式…...
外包做了1个月,技术退步一大半了。。。
先说一下自己的情况,本科生,20年通过校招进入深圳某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...
docker-compose常用命令及.yaml配置模板
1、docker-compose常用命令: docker-compose -f mysql-docker-compose.yaml up -d docker-compose -f mysql-docker-compose.yaml downdocker-compose的常用命令包括: docker-compose up:启动并运行Compose文件中的服务。 docker-compose st…...
工作随机:OEM(13.5)报错代理无法访问
文章目录 前言一、问题排查二、重启主机agent1.定位主机安装位置2.查看并启动agent3.OEM检查 前言 今早接到反馈,在客户部署的OEM(版本 13.5)监控失效,提示代理无法访问,无法访问的除了数据库以外还有主机都显示数据不…...
Pruning Papers
[ICML 2020] Rigging the Lottery: Making All Tickets Winners 整个训练过程中mask是动态的,有drop和grow两步,drop是根据权重绝对值的大小丢弃,grow是根据剩下激活的权重中梯度绝对值生长没有先prune再finetune/retrain的两阶段过程 Laye…...
C#COM对象的资源释放
在C#中使用COM对象时,由于COM对象遵循引用计数(Reference Counting)的管理方式,当COM对象的引用计数为0时,系统才会真正释放该COM对象所占用的资源。然而,在.NET环境下,CLR(Common L…...
了解Apache 配置与应用
本章内容 理解 Apache 连接保持 掌握 Apache 的访问控制 掌握 Apache 日志管理的方法 Apache HTTP Server 之所以受到众多企业的青睐,得益于其代码开源、跨平台、功能 模块化、可灵活定制等诸多优点,不仅性能稳定,在安全性方面的表现也十分…...
悟的复杂度分析
复杂度分析: 时间复杂度(算法中的基本操作的执行次数); 空间复杂度。 时间复杂度: 实际上我们计算时间复杂度时,我们其实并不需要计算准确的执行次数,只需要大概的执行次数,因此我们…...
《网络是怎样连接的》2.5节图表(自用)
图5.1:ip包结构 图5.2:ip网络包的传输方式 1.以太网的部分也可以替换成其他的东西,例如无线局域网、ADSL、FTTH等,它们都可以替代以太网的角色帮助IP协议来传输网络包 2.根据ARP协议,客户端可以根据ip地址得到下一个路…...
java 音乐会售票平台系统Myeclipse开发mysql数据库struts2结构java编程计算机网页项目
一、源码特点 java 音乐会售票平台系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助struts2框架开发mvc模式,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发 环境为TOCAT7.0,Myeclipse8.5开发,数据…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
