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开发,数据…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...

基于小程序老人监护管理系统源码数据库文档
摘 要 近年来,随着我国人口老龄化问题日益严重,独居和居住养老机构的的老年人数量越来越多。而随着老年人数量的逐步增长,随之而来的是日益突出的老年人问题,尤其是老年人的健康问题,尤其是老年人产生健康问题后&…...