Ping程序的设计与实现
ping 原理

ping 原理
Ping是一种网络工具,用于测试主机之间的连通性。
它的原理是向目标主机发送一个小的网络数据包(ICMP报文),然后等待目标主机回复。
通过观察回复时间和成功率,可以评估目标主机的响应速度和连通性。
当执行ping命令时,操作系统会创建一个ICMP报文,并附上自己的IP地址和目标主机的IP地址。
然后,该报文将通过本地网络接口发送到目标主机。
一旦目标主机收到报文,它将从目标主机发送一个回复报文,其中包含原始数据包的部分或全部。
在收到回复报文后,ping工具会记录下往返时间(Round-Trip Time,RTT),这是发送报文到接收回复报文的时间间隔。
根据RTT可以判断目标主机的响应速度,通常以毫秒为单位。
另外,ping还会记录成功发送和接收报文的次数,用于计算成功率。
成功率表示在一定时间内成功传送数据包的比例。
通常以百分比表示。
通过连续发送ping报文并收集回复报文,可以得到目标主机的平均响应时间和连通性情况。
ping工具通常会输出每个报文的序列号、发送时间、回复时间和成功率等信息,帮助用户分析网络延迟和故障。
需要注意的是,由于网络拥塞、目标主机故障或防火墙限制等原因,ping命令可能会失败或延迟较高。
因此,在进行网络测
试时,应该综合考虑多个因素,并使用其他工具和技术进行更全面的评估。
Ping 程序设计原理(2023最新版)

Ping 程序设计原理⒈引言本文档旨在介绍 Ping 程序设计原理,包括其概述、设计原则和实现细节。
Ping 是一种网络工具,用于测试主机之间的网络连通性。
本文将讨论 Ping 的基本原理、实现方法以及使用示例。
⒉概述Ping 是一种基于 ICMP(Internet Control Message Protocol)的网络工具,它通过向目标主机发送 ICMP 回显请求消息(Echo Request)并等待目标主机的 ICMP 回显应答消息(Echo Reply)来测试主机之间的连通性。
⒊设计原则在设计 Ping 程序时,需要考虑以下原则:- 网络层协议:Ping 使用 ICMP 协议进行通信,所以需要对ICMP 协议进行理解和实现。
- 数据包处理:Ping 程序需要构造 ICMP 回显请求消息,并解析目标主机的 ICMP 回显应答消息。
- 超时机制:Ping 程序需要设置合理的超时时间,如果在超时时间内未接收到回显应答,则认为连接超时。
- 循环测试:Ping 程序可以通过循环发送 ICMP 回显请求消息来进行连通性测试。
⒋实现细节⑴ ICMP 协议ICMP 是一种网络层协议,用于在 IP 网络中传递错误消息和操作性消息。
在 Ping 程序中,我们使用 ICMP 协议来进行主机之间的连通性测试。
⑵构造 ICMP 回显请求消息Ping 程序在发送 ICMP 回显请求消息时,需要构造相应的数据包。
构造 ICMP 数据包过程需要设置以下字段:- 类型:设置为 8,表示 ICMP 回显请求消息。
- 代码:通常设为 0。
- 校验和:对 ICMP 数据包进行校验和计算。
- 标识符和序列号:用于识别 ICMP 回显请求消息和回显应答消息之间的对应关系。
- 数据:可以包含任意数据,用于传递给目标主机处理。
⑶解析 ICMP 回显应答消息Ping 程序在接收到目标主机的 ICMP 回显应答消息时,需要解析其内容。
解析 ICMP 数据包时,需要检查以下字段:- 类型:应为 0,表示 ICMP 回显应答消息。
完成ping的功能,能够方便的设置与ping指令相关的参数

一、任务概述及需求分析○1编写一个网络应用程序。
○2基本要求:完成ping的功能,能够方便的设置与ping指令相关的参数(至少两项参数:-n count和-l size);不限实现的方式和语言。
说明:最低要求在给的例程中进行修改,更高级要求为做出图形化界面○3扩展要求:实现trace route的功能二、ICMP协议分析ICMP是(Internet Control Message Protocol)Internet控制报文协议。
它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。
控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。
这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
图2-1 ICMP在协议框架中的位置图2-2 ICMP协议帧格式报文类型分为两类:○1差错报告Error-Reporting:报告路由器或目的站点处理一个ip分组时可能遇到的一些问题○2测试查询Query:帮助主机或管理员从某一个路由器或主机获得一些特定的信息图2-3 ICMP报文类型及作用三、代码框架及流程图图3-1 程序流程图图3-2 代码框架四、重要函数分析○1IP报头格式struct IPHeader {BYTE h_len:4; // Length of the header in dwordsBYTE version:4; // Version of IPBYTE tos; // Type of serviceUSHORT total_len; // Length of the packet in dwordsUSHORT USHORT ident; // unique identifierUSHORT flags; // FlagsBYTE ttl; // Time to liveBYTE proto; // Protocol number (TCP, UDP etc)USHORT checksum; // IP checksumULONG source_ip;ULONG dest_ip; };○2ICMP报头格式struct ICMPHeader {BYTE type; // ICMP packet typeBYTE code; // Type sub codeUSHORT checksum;USHORT id;USHORT seq;ULONG timestamp; // not part of ICMP };○3Raw SocketSOCKET sd;sd=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,0,0,0); setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)&ttl, sizeof(ttl)) ;RawSocket的作用主要在三个方面:1.通过raw socket来接受发向本机的ICMP,IGMP协议包,或者用来发送这些协议包.2.接受发向本机的但TCP/IP栈不能够处理的IP包.3.用来发送一些自己制定源地址特殊作用的IP包(自己写IP 头,TCP头等)○4Struct of addressstruct sockaddr_in{u_short sin_family;u_short sin_port;struct in_addr sin_addr;char sin_zero[8];}struct in_addr{union {struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;struct { u_short s_w1,s_w2; } S_un_w;u_long S_addr;}S_un; }○5Set addresssockaddr_in dest, source;dest.sin_family = AF_INET;dest.sin_addr.s_addr = inet_addr(host);○6Initial Send_buf && Calculate checksumallocate_buffers(send_buf, recv_buf, packet_size)Sizeof(ICMPHeader)<=Packet_size <=MAX_DATA_SIZE icmp_hdr->type = ICMP_ECHO_REQUEST;icmp_hdr->code = 0;icmp_hdr->checksum = 0;icmp_hdr->id = (USHORT)GetCurrentProcessId();icmp_hdr->seq = seq_no;icmp_hdr->timestamp = GetTickCount();const unsigned long int deadmeat = 0xDEADBEEF;char*datapart=(char*)icmp_hdr + sizeof(ICMPHeader);int bytes_left = packet_size - sizeof(ICMPHeader);while (bytes_left > 0) {memcpy(datapart,&deadmeat,min(int(sizeof(deadme at)), bytes_left));bytes_left -= sizeof(deadmeat);datapart += sizeof(deadmeat);}USHORT ip_checksum(USHORT* buffer, int size){unsigned long cksum = 0;while (size > 1) {cksum += *buffer++;size -= sizeof(USHORT);}if (size) {cksum += *(UCHAR*)buffer;}cksum = (cksum >> 16) + (cksum & 0xffff);cksum += (cksum >> 16);return (USHORT)(~cksum);}○7Send _tosend_buf = icmp_hdr;sendto(sd, (char*)send_buf, packet_size, 0, (sockaddr*)&dest, sizeof(dest));○8recvfromrecvfrom(sd, (char*)recv_buf,packet_size + sizeof(IPHeader), 0,(sockaddr*)&source, &fromlen);五、代码实现结果(截图)1.Ping清水河畔论坛202.115.22.221,能探测到此主机。
计算机网络课程设计题目

计算机网络课程设计一.中小型千兆网吧组建内容及要求:用BOSON软件实现小规模网络的模拟。
熟悉对路由器和交换机的配置命令,调通网络,并通过实例深入理解网络基本工作原理及实现方法。
学会网络构建、日常IP地址1.2.3.4.5.6.写出课程设计报告:设计目的、设计内容、设计方案、拓扑图、设备选型、方案报价、子网划分等内容。
(1)企业网络工程(2)银行网络工程(3)医院网络工程(4)校园网网络工程(5)大型机场信息网络工程(6)邮电综合管理信息网(7)某航空公司网络系统建设(8)某市宽带信息网络(9)证券交易网络系统(10)学校以太网网络建设三.Ping程序的设计与实现设计的目的是使学生掌握网络层协议的原理及实现方法。
设计内容,在给定的Ping程序的基础上做如下功能扩充:●-h 显示帮助信息●●●PingPing消息。
ICMPIdentification,Flags,FragmentOffset用于IP包分段TimetoLiveIP包的存活时长ProtocolICMP=1Addresses发送Echo消息的源地址是发送Echoreply消息的目的地址,相反,发送Echo消息的目的地址是发送Echoreply消息的源地址。
Ping实际上是使用ICMP中的ECHO报文来实现的。
Echo或EchoReply消息格式如下:012301234567890123456789012345678901+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Type|Code|Checksum|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Identifier|SequenceNumber|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Data...+-+-+-+-+-Typeecho消息的类型为8echoreply的消息类型为0。
ping 命令 原理

ping 命令原理
ping命令使用Internet控制消息协议(ICMP)来测试网络连接和测量往返时间(RTT)。
它通过发送ICMP回显请求消息
(称为ping请求)到目标主机,并等待对应的回复消息
(ping响应)来确定主机的可达性和延迟。
当使用ping命令时,计算机会发送一个ICMP Echo Request消息到目标主机,该消息包含有关发送时间的时间戳。
目标主机收到消息后,会生成一个ICMP Echo Reply消息并将其发送回
计算机。
计算机根据收到回复的时间戳和发送时间戳之差来计算往返时间(RTT)。
通过连续发送ping请求并计算RTT,可以检测网络是否正常、主机是否可达以及网络的延迟情况。
ping结果中通常包括目标主机的IP地址、ping请求和响应的往返时间,以及丢包率等
信息。
需要注意的是,由于ping命令使用ICMP协议,因此需要在
目标主机所在的网络中启用ICMP回显请求和回复。
有些网络可能为了安全性而禁用了ICMP,因此在ping请求中可能会收到“请求超时”或“目标主机不可达”的错误消息。
总结起来,ping命令通过发送ICMP回显请求并接收回复消息来测试网络连接和测量往返时间(RTT),以便检测主机可达性和网络延迟情况。
ping程序设计与实现课程设计

ping程序设计与实现课程设计一、课程目标知识目标:1. 学生能理解ping程序的工作原理,掌握网络诊断的基本方法。
2. 学生能描述IP协议、ICMP协议的基本概念及其在ping程序中的应用。
3. 学生了解计算机网络的通信原理,掌握如何利用ping程序检测网络连通性。
技能目标:1. 学生能运用所学知识,独立编写简单的ping程序。
2. 学生通过实践操作,提高问题分析及解决能力,具备基本的网络诊断技巧。
3. 学生掌握使用编程工具(如:IDE、编译器等)进行代码编写、调试和优化。
情感态度价值观目标:1. 学生培养对计算机网络的兴趣,激发学习编程的热情。
2. 学生在学习过程中,培养团队协作、沟通表达的能力,增强自信心。
3. 学生通过本课程的学习,认识到网络技术在实际应用中的重要性,培养对网络安全的责任感。
分析课程性质、学生特点和教学要求,本课程旨在让学生掌握ping程序的设计与实现,结合实际操作,提高学生的编程能力和网络诊断技巧。
课程目标具体、可衡量,有助于教师进行教学设计和评估。
通过本课程的学习,学生将具备基本的网络编程知识和技能,为今后的学习和工作打下坚实基础。
二、教学内容1. 网络基础知识回顾:IP协议、ICMP协议、网络层通信原理。
2. ping程序工作原理:发送ICMP请求、接收ICMP回复、计算往返时间(RTT)。
3. 编程语言基础:C语言或Python语言的基本语法,重点掌握数据类型、控制结构、函数定义。
4. ping程序设计与实现:- 环境搭建:安装编程工具、配置网络环境。
- 代码编写:根据ping程序工作原理,编写发送和接收ICMP请求的代码。
- 调试与优化:调试代码,处理异常情况,优化程序性能。
5. 实践操作:分组进行实际操作,组内讨论、分析问题,相互协作完成ping 程序编写。
6. 网络诊断技巧:运用ping程序检测网络连通性,分析网络延迟、丢包等问题。
教学内容安排和进度:第一课时:网络基础知识回顾,介绍ping程序工作原理。
编程模拟ping程序

一、实验题目编程模拟ping程序,实现Ping程序的基本功能,即接收到一个ping程序数据包后给出回应。
二、原理概述ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。
ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,这有点象潜水艇声纳系统中使用的发声装置。
想要了解ping命令的原理必须了解ICMP协议、ICMP报文格式和IP报文格式。
(1)ICMP报文结构ICMP 报文结构: ICMP 报文前四个字节为报文头部分,第一个字节为报文类型,第二个字节未用, 第三四个字节为报文的校验和。
从第四个字节开始为长度可变的数据段,该段的内容取决于ICMP 的类型,本文所要使用的请求报文和请求应答报文的数据段中前四个字节是报文的标识符和顺序号。
对于整个ICMP 报文来说其长度最长不能超过64K字节。
ICMP 报文结构如图1 所示。
0 7 8 15 16 31 32 47 48 63 64(2)IP报文结构ICMP 报文和其它位于IP 层的报文一样是作为IP 报文的数据段加上IP 报文头组成IP 数据报发出,其中IP 报文头长度一般为20 个字节。
如图2所示。
三、设计方案根据实验题目查找相关资料,熟悉及理解ping的工作原理,从而进一步设计ping程序的功能图和系统流程图。
准备工作做好后就可上机调试,验证其可行性并查找漏洞,完善ping程序。
(1) ping程序的设计包含了4部分:IP、ICMP的头结构,主函数模块,CMP数据包校验和的计算和使用说明模块。
(2)系统流程图首先在主函数里定义变量同时进行初始化,然后检查参数的正确性,如果参数不正确或者没有输入参数,则显示用户帮助信息(Usage ),并结束程序;如果参数正确,则对指定目的地执行Ping命令,如果Ping通,则显示Ping结果并释放占用资源,如果没有Ping通,则报告错误信息,并释放占用资源。
Linux网络编程基础(4)--Ping的C代码实现

Linux⽹络编程基础(4)--Ping的C代码实现1、背景 在进⾏⽹络编程的时候,通常使⽤的协议有TCP协议,UDP协议。
这些协议在简历套接字之初需要制定套接字的类型,⽐如TCP应当设置为 SOCK_STREAM,UDP对应的套接字应当设置为SOCK_DGRAM。
但是这些套接字并⾮能够提供⽹络所需的全部功能,我们还需要其他的套接字,⽐如原始套接字OCK_RAW。
原始套接字可以提供SOCK_STREAM和SOCK_DGRAM所不及的能⼒。
⽐如:(1)有了原始套接字,进程可以读取ICMPV4、ICMPV6、IGMP等的分组。
正如ping所使⽤的套接字,就是SOCK_RAW类型的。
这样使得使⽤ICMP和IGMP的程完全能够作为⽤户进程处理,⽽⽆需向内核添加代码。
(2)有了原始套接字,进程可以处理内核不处理其协议字段的IPV4数据报。
(3)有了原始套接字,进程使⽤IP_HDRINCL套接字选项定制⾃⼰的IPV4头部。
当然,上述的三个功能,并不是本⽂都要涉及的;只关注第⼀个能⼒,编写代码,实现ping程序。
2、基本使⽤ a.定义原始套接字与定义其他套接字没有形式上的巨⼤差别。
int sockfd; sockfd = socket(AF_INET, SOCK_RAW, protocol); protocol 的值是型为 IPPROTO_XXX的量,这些量定义在<netinet/in.h>中,⽐如ping使⽤的 IPPROTO_ICMP(关于IPV6的实现,再后续补充)。
只有超级⽤户才可以创建SOCK_RAW类型的套接字。
b. 原始套接字并不存在端⼝的概念。
可以在原始套接字上调⽤bind函数,但是这么做并不常见。
bind函数会设置发送数据报的源IP地址,如果没有使⽤ bind函数,那么内核将出发的借⼝地址作为源地址。
c. 同样,⼀般不会使⽤connect函数,connect函数会指定⽬的地址,但是因为原始套接字不存在端⼝概念,所以connect函数并不重要了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Ping程序的设计与实现Ping的基本实现原理请参考以下文档:/view/e0769dc69ec3d5bbfd0a7476.html;/view/9ee3583143323968011c9213.html;初学者读代码请先百度:socket(),setsockopt(),HeapAlloc()等函数。
使用说明:1、找到\Debug\ping.exe (即生成的可执行文件的目录);(Ping是工程名)2、开始->运行->cmd进入命令提示符模式;3、cd \Debug\ping.exe;然后输入参数即可。
Ping程序源码(无注释)//Ping.h#define WIN32_LEAN_AND_MEAN#include<windows.h>#include<winsock2.h>#include<ws2tcpip.h>#include<stdio.h>#include<stdlib.h>typedef struct tagIP_HEADER{unsigned int h_len:4;unsigned int ver:4;unsigned char tos;unsigned short total_len;unsigned short ident;unsigned short frag_floags;unsigned char ttl;unsigned char protocol;unsigned short checksum;unsigned int sourceip;unsigned int destip;}IP_HEADER,*PIP_HEADER;typedef struct tagIP_OPT_HEADER{unsigned char code;unsigned char len;unsigned char ptr;unsigned long addr[9];}IP_OPT_HEADER,*PIP_OPT_HEADER;typedef struct tagICMP_HEADER{unsigned char type;unsigned char code;unsigned short checksum;unsigned short id;unsigned short seq;unsigned long timestamp;}ICMP_HEADER,*PICMP_HEADER;#define DEF_PACKET_SIZE 32#define MAX_PACKET_SIZE 1024#define ICMP_ECHO 8#define ICMP_ECHOREPL Y 0#define IP_RECORD_ROUTER 7void usageinfo(char *progname);void FillIcmpData(char *icmp_data,int size);USHORT CheckSum(USHORT *buf,int size);void DecodeIcmpHeader(char *buf,int ret,LPSOCKADDR_IN lpSin); void DecodeIpHeader(char *buf,int bytes);//Ping.cpp#include<stdio.h>#include"Ping.h"#pragma comment(lib,"ws2_32")int main(int argc,char *argv[]){if(argc==1){usageinfo(argv[0]);return -1;}BOOL bRecordRout =FALSE;SOCKET hSocket =INV ALID_SOCKET;SOCKADDR_IN dstSin;SOCKADDR_IN fromSin;IP_OPT_HEADER ipOptHeader;char* pIcmpData = NULL;char* pRecvData = NULL;char* lpDstIp =NULL;int datasize =DEF_PACKET_SIZE;int ret;int rcvNum;for(int i=1;i<argc;i++){if(strchr(argv[i],'-')){switch(tolower(argv[i][1])){case 'r':bRecordRout=TRUE;break;case 'd':datasize=atoi(argv[i+1]);i=argc+1;break;}}else if(strchr(argv[i],'.')){int l=strlen(argv[i]);if(l<7||l>15)usageinfo(argv[0]);elselpDstIp=argv[i];}}WSADATA wsaData;WORD wVer=MAKEWORD(2,2);if(WSAStartup(wVer,&wsaData)!=0){printf("WSAStartup Error!\n");return -1;}hSocket=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);if(hSocket==INV ALID_SOCKET){printf("WSASocket Error,Code:%d",WSAGetLastError());WSACleanup();return -1;}if(bRecordRout){ZeroMemory(&ipOptHeader,sizeof(ipOptHeader));ipOptHeader.code=IP_RECORD_ROUTER;ipOptHeader.len=39;ipOptHeader.ptr=4;if((ret=setsockopt(hSocket,IPPROTO_IP,IP_OPTIONS,(char*)&ipOptHeader,sizeof(ipOptH eader)))==SOCKET_ERROR){printf("setsockopt(IP_OPTIONS)error,code:%d",WSAGetLastError());WSACleanup();closesocket(hSocket);return -1;}}int timeout=1000;if((ret=setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout )))==SOCKET_ERROR){printf("setsockopt(SO_RCVTIMEO)error,code:%d",WSAGetLastError());WSACleanup();closesocket(hSocket);return -1;}if((ret=setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout )))==SOCKET_ERROR){printf("setsockopt(SO_SNDTIMEO)error,code:%d",WSAGetLastError());WSACleanup();return -1;}pIcmpData=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET _SIZE);pRecvData=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET _SIZE);if(pIcmpData==NULL||pRecvData==NULL){printf("HeapAlloc Error\n");WSACleanup();return -1;}datasize+=sizeof(ICMP_HEADER);ZeroMemory(&dstSin,sizeof(dstSin));dstSin.sin_family=AF_INET;dstSin.sin_addr.s_addr =inet_addr(lpDstIp);FillIcmpData(pIcmpData,datasize);printf("Ping %s with %d bytes of data\n",inet_ntoa(dstSin.sin_addr),datasize);int count=0;int seq=0;rcvNum=0;while(1){count++;if(count==5)break;((PICMP_HEADER)pIcmpData)->checksum=0;((PICMP_HEADER)pIcmpData)->seq=seq++;((PICMP_HEADER)pIcmpData)->timestamp=GetTickCount();((PICMP_HEADER)pIcmpData)->checksum=CheckSum((USHORT*)pIcmpData,datasize);if((ret=sendto(hSocket,pIcmpData,datasize,0,(LPSOCKADDR)&dstSin,sizeof(dstSin)))==S OCKET_ERROR){if(WSAGetLastError()==WSAETIMEDOUT){printf("time out.\n");continue;}else{printf("sendto error,code:%d",WSAGetLastError());closesocket(hSocket);WSACleanup();return -1;}}int fromLen=sizeof(fromSin);if((ret=recvfrom(hSocket,pRecvData,MAX_PACKET_SIZE,0,(sockaddr*)&fromSin,&from Len))==SOCKET_ERROR){if(WSAGetLastError()==WSAETIMEDOUT){printf("time out.\n");continue;}printf("recvform fail!\n");closesocket(hSocket);WSACleanup();return -1;}rcvNum++;DecodeIcmpHeader(pRecvData,ret,&fromSin);}printf("\n Ping Statistics for :%s\n",lpDstIp);printf("\t Send=%d Received=%d,Lost=%d(%d%%loss)",4,rcvNum,4-rcvNum,(4-rcvNum)/4*100);if(hSocket!=INV ALID_SOCKET)closesocket(hSocket);HeapFree(GetProcessHeap(),0,pIcmpData);HeapFree(GetProcessHeap(),0,pRecvData);WSACleanup();return 0;}void usageinfo(char *progname){printf("Pingtool,byblode(********************.cn\n)");printf("usage:ping[-r]<host ip>[-d][data size]\n");printf("\t-r:\trecord router\n");printf("\thost ip:\thost ip to ping\n");printf("\t-d:\tuse data size option\n");printf("\tdata size:\tdata size to ping(<=1024)\n");}void FillIcmpData(char *icmp_data,int size){ICMP_HEADER *icmpHdr;icmpHdr=(PICMP_HEADER)icmp_data;icmpHdr->checksum=0;icmpHdr->code=0;icmpHdr->id=(unsigned short)GetCurrentProcessId();icmpHdr->seq=0;icmpHdr->type=ICMP_ECHO;icmpHdr->timestamp=0;}USHORT CheckSum(USHORT *buf,int size){USHORT cksum=0;while(size>1){cksum+=*buf++;size-=sizeof(USHORT);}if(size)cksum+=*buf++;cksum=(cksum>>16)+(cksum&0xffff);cksum+=(cksum>>16);return (USHORT)(~cksum);}void DecodeIcmpHeader(char *buf,int ret,LPSOCKADDR_IN lpSin) {ICMP_HEADER *icmpHdr;IP_HEADER *ipHdr;int ipHdrLen;static int first=0;DWORD tick=GetTickCount();ipHdr=(IP_HEADER*)buf;ipHdrLen=ipHdr->h_len*4;if(ipHdrLen==60&&!first)DecodeIpHeader(buf,ret);icmpHdr=(ICMP_HEADER *)(buf+ipHdrLen);if(icmpHdr->type!=ICMP_ECHOREPL Y){printf("no echo reply %d recved\n",icmpHdr->type);return ;}if(icmpHdr->id!=(USHORT)GetCurrentProcessId()){printf("someone else's packet!\n");return;}printf("Reply form: %s",inet_ntoa(lpSin->sin_addr));printf("\tbytes: %d icmp seq: %d TTL=128",ret,icmpHdr->seq);printf("time: %dms\n",tick-icmpHdr->timestamp);first++;return;}void DecodeIpHeader(char *buf,int bytes){IP_OPT_HEADER *ipOptHdr;IN_ADDR in;ipOptHdr=(IP_OPT_HEADER *)(buf+20);printf("Record Router:");for(int i=0;i<(ipOptHdr->ptr/4)-1;i++){in.S_un.S_addr=ipOptHdr->addr[i];printf("\t%-15s\n",inet_ntoa(in));}}。