课程设计---Ping程序设计与实现
Ping程序的设计与实现

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));}}。
计算机网络课程设计(ping)

计算机网络课程设计Ping程序设计(后附源码)四川大学黄昊1143041195一.设计目标二.ICMP包结构三.校验和计算四.代码实现a)ICMP封包b)ICMP包转换成字节数组c)域名解析、选择IPv4地址d)原始套接口e)计算校验和五.运行结果六.总结一、设计目标本程序设计实现基本的ping程序功能,包括域名解析,ICMPv4回显包发送,统计丢失率等功能。
二、ICMP包结构ICMP包包含在IP包结构之内,是去除IP包头的部分,C#提供的Raw Socket功能可以实现包装ICMP结构,但自动包含IP包头等结构。
ICMP包由1Byte类型、1Byte SubCode、2字节校验和、2字节标示符、2字节序号,若干字节数据组成。
其结构图如下:4Byte类型号8 、子代码表示ICMP回显功能,默认标示符45、序号0、Data小节可填充数据,本程序填充了ASCII码‘a’十六进制61,填充24字节,所以整个包大小共32字节。
三、校验和计算对于ICMP包中的校验和,首先将校验和填0之后再整体计算。
计算时,按照2字节为一个单位累加,最后将所有溢出结果再次做加法,最后整体取反,返回一个2字节长的校验和。
具体计算方法伪代码如下:Int32 cksum = 0;for (int i = 0; i < 16; i++){cksum += ConvertToUInt16(packet, i * 2);}cksum = (cksum >> 16) + (cksum & 0xffff);cksum += (cksum >> 16);return (ushort)(~cksum);四、代码实现a)实现难度1:封装ICMP包。
为了方便操作与计算,在C#中,创建了一个ICMP包的结构体。
为了使包的逻辑结构与实际发送的结构一样,借助了C#提供的一个机制,叫非托管内存布局,使用StructLayoutAttribute属性,其中参数LayoutKind.Sequential指定了整个结构体的数据堆放方式为顺序堆放,保证内存中数据的连续性。
计算机网络基础课程设计Ping程序实现

计算机网络基础课程设计Ping程序实现计算机网络工程课程设计报告题目:Ping程序的实现学生姓名:学号:专业班级:计科专业班同组姓名: 指导教师:设计时间:2022年下学期第某周指导老师意见:评定成绩:签名:日期:年月日目录一、课程设计的目的和意义2二、课程设计的内容和要求21.内容:22.要求:2三、课程设计的相关技术2四、课程设计过程21.Ping主模块22.功能控制模块43.数据报解析模块5五、课程设计小结6六、参考文献7七、附录(程序清单)7八、心得体会11一、课程设计的目的和意义利用ICMP数据包、C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间的连通情况。
通过本程序的训练,使学生熟悉ICMP报文结构,使学生对ICMP有更深的理解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。
二、课程设计的内容和要求1.内容:用C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间的连通情况。
2.要求:1)独立完成程序的设计、编码和调试。
2)系统利用C语言实现,程序调试环境为TurboC或VC;3)按照课程设计规范书写课程设计报告。
4)采用VC环境进行调试运行。
三、课程设计的相关技术由于Ping程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。
为了实现直接对IP和ICMP包进行操作,实验中使用RAW模式的ocket编程。
首先定义IP数据报首部,在IP数据报的基础上定义ICMP数据报首部,并初始化一些全局变量。
接着自定义填充ICMP数据报字段函数FillICMPData()、校验和函数checkum()、解读ICMP报首部函数DecodeICMPHeader()、释放资源函Cleanup()。
最后主函数通过调用这些函数来实现Ping命令功能。
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命令的设计与实现》专业班级计科094 同组人姓名同组人学号实验日期2013-04-10 指导教师成绩2013 年 04 月 10 日设计目的和要求1、实验目的:Ping命令向目的主机发送ICMP ECHO—REQUEST请求并接收目的主机返回的响应报文,用来检验本地主机和远程的主机是否连接。
2.实验要求:利用ICMP数据包,测试主机的连通性,通过课程设计,使学生熟悉ICMP报文结构,使学生对ICMP有更深的理解。
要求:输出参考系统自带ping程序,命令行运行:ping ip二、设计说明设计分析:使用原始套接字可以读写ICMP分组,利用原始套接字发送ICMP回显请求,并接收ICMP 回显应答,通过icmp_send()发送ICMP回显示请求包,icmp_recv()接收ping目的主机的回复,并使用终端信号处理函数SIGINT处理信号,建立两个线程,一个用于发送数据,另一个用于接收响应数据,主程序等待两个线程运行完毕后再进行下一步动作。
最后,主程序讲发送数据和接收的数据进行统计,并将结果打印出来。
系统运行环境:虚拟机:Fedora14(linux操作系统) gcc设计中的重点和难点:ICMP数据包的打包和解包,以及从CRC16校验算法的分析实现输入和输出条件:在linux系统下运行ping 在出现4个响应包后按Ctrl+c键停止发送。
三、系统详细设计《Ping命令的设计与实现》Ping命令向目的主机发送ICMP ECHO—REQUEST请求并接收目的主机返回的响应报文,用来检验本地主机和远程的主机是否连接。
协议格式图1.1中已经对ICMP协议的报文格式进行了说明。
Ping 的客户端方式的类型为8,代码值为0,表示ICMP的回显请求。
类型为0,代码为0是,是ICMP回显应答。
检验和为16为的crc16 的算法。
0 7 8 15 16 31图1.1 ICMP报文的数据格式图1.2所示为ping所使用的类型和代码格式。
ping程序的设计与实现

ping程序的设计与实现
Ping程序的设计与实现是通过一种单向测量技术来实现的,它可以用来评估网络的性能、访问故障和网络可用性。
Ping程序工作时会首先向目标主机发送一个ICMP(网际控制报文协议)报文,然后等待目标主机的应答。
在实现ping程序的过程中,首先要为发送的ICMP数据报定义一个数据结构,这个数据结构将包含所有必要的信息,如报文类型、报文代码、校验和等。
其次,要实现函数,对这个数据结构进行填充和序列化,以便将ICMP报文发送出去。
实现发送ICMP报文后,就要开始接收应答。
为此,可以利用Socket API来创建一个Raw Socket,以便从网络上接收ICMP报文,并将其解码为数据结构,以便能够识别是哪一条报文的应答。
最后,还需要实现超时,用来处理因网络拥塞或丢包等原因导致的应答报文没有收到的情况。
这可以通过在发送ICMP报文之前先设置一个定时器,当定时器到期时,就可以判断该报文没有收到应答报文而超时。
以上就是ping程序的大致设计与实现方式,整个实现的过程可以大体分为发送ICMP数据报、接收应答和超时处理三部分。
这些都需要对数据报结构进行定义和填充,以及使用Socket API创建Raw Socket 来发送和接收数据,并通过设置定时器来实现超时处理,以保证ping 程序可以正常工作。
计算机网络课程设计

成绩:课程设计报告设计名称:计算机网络课程设计设计项目:基于ICMP协议的ping命令设计与实现姓名:孙泽宇专业:计算机科学与技术学院班级:计算机14-5班学号:1404010522计算机科学与技术学院2016年12月23 日目录一、课程设计的目的和意义PING程序是我们使用的比较多的用于测试网络连通性的程序。
PING程序基于ICMP,使用ICMP的回送请求和回送应答来工作。
由计算机网络课程知道,ICMP 是基于IP的一个协议,ICMP包通过IP的封装之后传递。
二、课程设计的内容和要求PING程序是用于测试网络连通性的程序。
要求在WINDOWS环境下实现基本的PING 程序功能. 在命令提示符下输入: PING ***.***.***.*** 其中***为目的主机的IP地址,不要求支持域名,对是否带有开关变量也不做要求。
不带开关变量时,要求返回4次响应。
返回信息的格式 REPLY FROM ***.***.***.*** 或TimeOut (无法PING通的情况)三、设计用设备仪器1.pc机2.Myeclipse软件四、课程设计的相关技术ping 程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接。
ping 使用的是ICMP协议,它发送ICMP回送请求消息给目的主机。
ICMP协议规定:目的主机必须返回ICMP回送应答消息给源主机。
如果源主机在一定时间内收到应答,则认为主机可达。
ICMP协议通过IP协议发送的,IP协议是一种无连接的,不可靠的数据包协议。
因此,保证数据送达的工作应该由其他的模块来完成。
其中一个重要的模块就是ICMP(网络控制报文)协议。
当传送IP数据包发生错误--比如主机不可达,路由不可达等等,ICMP协议将会把错误信息封包,然后传送回给主机。
给主机一个处理错误的机会,这也就是为什么说建立在IP层以上的协议是可能做到安全的原因。
ICMP 数据包由8bit的错误类型和8bit的代码和16bit的校验和组成。
ping程序设计与实现

测试结果如下:
1.
2.
错误分析:
1. Request Timed Out a.提到的对方可能装有防火墙或已关机以外,还有就是本机的IP不正确和网关设置错误。 b.IP不正确:IP不正确主要是IP地址设置错误或IP地址冲突。
2. Destination Host Unreachable
a.如果局域网中使用DHCP分配IP时,而碰巧DHCP失效,这时使用 PING命令就会产 生此错误。
1.初始化模块 2.功能控制模块 3.数据控制模块 4.数据 Nhomakorabea解读模块
5. ping测试模块
程序测试:
1. Ping127.0.0.1,127.0.0.1回送地址Ping回送地址是为了检 查本地的TCP/IP协议有没有设置好。 2. Ping远程IP地址,这主要是检查本网或本机与外部的连接是否 正常。
ping的程序设计与实现
1.设计目的:本程序设计主要解决在本地的电脑上去 查看别的网站和本机电脑的连通性,检查本机是否可以 在浏览器上访问到该网站。
2.开发平台:在课程设计中,系统开发平台为
Windows xp或者Windows 7,程序设计设计语言采 用Visual C++来实现。
本程序设计的五个模块:
b.另外子网掩码设置错误也会出现这错误。
c.比较特殊就是路由返回错误信息,它一般都会在"Destination Host Unreachable"前加 上IP地址说明哪个路由不能到达目标主机。这说明你的机器与外部网络连接没有问题, 但与某台主机连接存在问题。
谢谢各评委老师 以及在座的小伙伴们!
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计课程名称____计算机网络_____题目名称_Ping程序设计与实现学生学院____计算机学院____专业班级____08计科4班___学号_______2011年 1 月8 日一、课程设计目的本次课程设计的目的旨在通过网络相关程序的编写,使我们能深入理解TCP/IP协议机制,以及初步掌握基于Winsocket的网络编程技术。
同时巩固相关的理论知识,为以后程序开发打下良好而又坚实的基础。
二、知识准备1、ICMP协议互联网控制信息协议(Internet CONTROL Message Protocol),用于错误报告和调试。
该协议是TCP/IP协议集中的一个子协议,属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。
当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。
我们可以通过Ping命令发送ICMP回应请求消息并记录收到ICMP回应回复消息,通过这些消息来对网络或主机的故障提供参考依据。
常见ICMP报文有响应请求报文,目标不可到达、源抑制和超时报文,此外还有时间戳报文。
2、Ping工作原理Ping的原理就是首先建立通道,然后发送包,对方接受后返回信息,这个包至少包括以下内容:发送的时候,包的内容包括对方的ip地址和自己的地址,还有序列数;回送的时候包括双方地址,还有时间等,主要是接受方在都是在操作系统内核里做好的,时刻在监听。
Ping程序生成一个icmp“回送请求”,将其发送给目的主机。
通过检测是否可以收到目标主机的应答,便可以知道网络的连通性。
(3) Tracert 工作原理透过向目标发送不同 IP 生存时间 (TTL) 值的ICMP回应数据包,Tracert 诊断程序确定到目标所采取的路由。
要求路径上的每个路由器在转发数据包之前至少将数据包上的 TTL 递减 1。
数据包上的 TTL 减为 0 时,路由器应该将“ICMP已超时”的消息发回源系统。
Tracert 先发送 TTL 为 1 的响应数据包,并在随后的每次发送过程将 TTL 递增1,直到目标响应或 TTL 达到最大值,从而确定路由。
透过检查中间路由器发回的“ICMP已超时”的消息确定路由。
三、界面设计及数据结构的说明1 、MFC界面设计建立流程步骤一:打开VC6.0,点击文件选项,在project选项卡中选择MFC Appwizard(exe),项目名称为ping。
步骤二:在新窗口中选择窗口类型为基于对话框的类型。
步骤三:设置界面选项步骤四:设置窗口类型步骤五:选择相应类,点击finish完成。
界面建立成功后添加相应按钮及功能模块。
主界面设计如下:2、数据结构的定义及说明(1)定义IP头部typedef struct _IpHeader{unsigned int HeaderLength:4; // 头部长度unsigned int Version:4; // IP版本号unsigned char TypeOfService; // 服务类型unsigned short TotalLength; // 收发包的总长度unsigned short Identification; // 唯一校验符unsigned short FragmentationFlags; // 标志位unsigned char TTL; // 生存时间unsigned char Protocol; // 协议类型 (TCP, UDP 等)unsigned short CheckSum; // IP头部校验和unsigned int sourceIPAddress; // 源地址unsigned int destIPAddress; // 目的地址} IpHeader;(2)定义ICMP头部typedef struct _IcmpHeader{BYTE IcmpType; //icmp类型BYTE IcmpCode; //编码类型USHORT IcmpChecksum; //icmp校验和USHORT IcmpId;USHORT IcmpSeq; //icmp序列号ULONG IcmpTimestamp; // 头部无标准定义,但仍需保留} IcmpHeader;(3)CIcmp类class CIcmp : public CSocket{public:BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents);BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents, int AFamily, int AType, int AProtocol);int CloseIcmpSocket(void);BOOL Connect(int ReceiveTimeout, int SendTimeout);BOOL Connect(LPINT ReceiveTimeout, LPINT SendTimeout, int AFamily, int AType, int AProtocol);int SetTTL(int TTL);int SetAsynchNotification(HWND hWnd, unsigned int Message, long Events);int Receive(LPSTR pIcmpBuffer, int IcmpBufferSize);unsigned long GetIPAddress (LPSTR iHostName);int Ping (LPSTR pIcmpBuffer, int IcmpBufferSize);unsigned short IcmpChecksum(unsigned short FAR *lpBuf, int Len);void DisplayError(CString ErrorType, CString FunctionName);public:CIcmp(void);CIcmp(CIcmp ©);~CIcmp(void);private:public:LPIcmpHeader pIcmpHeader;LPIpHeader pIpHeader;SOCKET icmpSocket;SOCKADDR_IN icmpSockAddr;SOCKADDR_IN rcvSockAddr;DWORD icmpRoundTripTime;DWORD icmpPingSentAt;DWORD icmpPingReceivedAt;int icmpRcvLen;int icmpHops;int icmpMaxHops;int icmpCurSeq;int icmpCurId;int icmpPingTimer;int icmpSocketError;int icmpSocketErrorMod;unsigned long icmpHostAddress;protected:};typedef CIcmp FAR * LPIcmp;(4)CPingPlusDlg类class CPingPlusDlg : public CDialog{enum ImageType{Icon_Blank,Icon_BlueArrow};private:void StopTimer();void StartTimer();void ChangeIconState(void);BOOL InitSockets();BOOL FetchWinsockSettings();BOOL LoadRegValues(void);void SaveRegValues();void SendPing(void);unsigned long HostIPAddress();void UpdateTrace ();void DisplayTrace(LPCSTR TripTimeMessage, LPCSTR IPAddressMessage, LPCSTR HostMessage); void EndTrace(void);void InitImageList();int AddListColumn(int column, int lfmt, int lmaxwidth, LPSTR ltext, int lsubitem);void DisplayBlankLine(void);void SetTraceSequence(int Seq, int FocusItem, ImageType FocusImage);void SetTraceFocus(int FocusItem, int FocusSubItem);void SetDisplayImage(int FocusItem, enum ImageType FocusImage);void TraceComment(CString Comment);public:CPingPlusDlg(CWnd* pParent = NULL); // 标准构造器protected:HICON m_hIcon;LRESULT OnPINGAsynch(WPARAM wParam, LPARAM lParam);public:CIcmp PingSocket; // Icmp 对象WSADATA wsaData; // Windows Socket 信息结构CString LocalNameServer;CString LocalDomainName; // 域名 (从注册机构获取)CString DefHost; // 默认主机名 (从注册机构获取)char HostName[MAXHOSTNAME]; // 将主机名加入到会话中去char CurrentHostName[MAXHOSTNAME]; // 当前正在ping的主机struct in_addr TraceTarget; // 操作路径终端BOOL TimerActive; // TRUE = 计时器到时unsigned long icmpIntervalCount; // 当前计时时间间距unsigned long icmpMaxIntervals; // 最大间距char icmpBuffer[MAX_PACKET]; // icmp操作的普通缓冲区LPSTR pIcmpBuffer; // icmp缓冲区的故障分析报告指向int icmpDataLen; // icmp发出信息的字节数 (不计算头部)int icmpPingTTL; // 路径操作所用到的ttl值BOOL icmpTracing;// TRUE = 路径操作, FALSE = PING操作BOOL PingSent; // TRUE = 等待ECHO回复, FALSE = 忽略输入};四、程序主题功能设计模块1、调用ping模块void CPingPlusDlg::OnPingButton(){IconState = 0;DisplayBlankLine ();icmpTracing = FALSE;icmpPingTTL = PingSocket.icmpMaxHops; //ping生存时间为最大icmp跳数PingSocket.icmpCurSeq = 0;//当前icmp序列为0SendPing ( );//开始执行ping}2、初始化socketBOOL CPingPlusDlg::InitSockets(){if (!PingSocket.OpenNewSocket(GetSafeHwnd(),WSA_PING_ASYNC,FD_READ | FD_WRITE,AF_INET,SOCK_RAW,IPPROTO_ICMP)){PingSocket.DisplayError ("WSA_PING_ASYNC","CPingPlusDlg::InitSockets");return FALSE;}return TRUE;}3、获取winsocket设置信息BOOL CPingPlusDlg::FetchWinsockSettings(){SysTCPIP STcpIp;if (!STcpIp.WinsockVersion(&wsaData)){MessageBox ("No valid winsock.dll detected","CPingPlusDlg::OnInitDialog",MB_OK|MB_SYSTEMMODAL);return FALSE;}if (!STcpIp.GetLocalHostName (&m_LocalHost)){gethostname(CurrentHostName, MAXHOSTNAME);}else{memcpy (CurrentHostName, m_LocalHost, m_LocalHost.GetLength());CurrentHostName[m_LocalHost.GetLength()] = 0;}m_LocalHost = CurrentHostName;if (!STcpIp.GetDomainName(&LocalDomainName))LocalDomainName = "";m_LocalHost += "." + LocalDomainName;memcpy (CurrentHostName, m_LocalHost, m_LocalHost.GetLength());CurrentHostName[m_LocalHost.GetLength()] = 0;if (!STcpIp.GetNSName (&LocalNameServer))LocalNameServer = "";m_NameServer = "Name Server: " + LocalNameServer;SetDlgItemText (IDC_LocalHost, m_LocalHost);SetDlgItemText (IDC_NameServer, m_NameServer); LoadRegValues();SetDlgItemText (IDC_DEST, HostName);return TRUE;}4、发送ping信息void CPingPlusDlg::SendPing(void){PingSent = TRUE;PingSocket.icmpCurSeq++;PingSocket.icmpCurId = (USHORT)GetCurrentProcessId(); PingSocket.icmpHostAddress = HostIPAddress();if (PingSocket.icmpHostAddress == NULL)return;if (icmpTracing){icmpPingTTL++; }if (PingSocket.SetTTL (icmpPingTTL) == SOCKET_ERROR) { PingSocket.DisplayError ("setsocket(TTL)","CPingPlusDlg::SendPing");return; }Sleep (100);// 用蓝色箭头显示序列号及相应信息SetTraceSequence (PingSocket.icmpCurSeq,m_TraceList.GetItemCount(),Icon_BlueArrow);PingSocket.icmpSockAddr.sin_family = PF_INET;PingSocket.icmpSockAddr.sin_addr.s_addr = PingSocket.icmpHostAddress;PingSocket.icmpSockAddr.sin_port = 0;StartTimer();if (PingSocket.Ping (pIcmpBuffer, icmpDataLen) == SOCKET_ERROR)PingSocket.DisplayError("Ping", "CPingPlusDlg::SendPing");}5、设置超时时间int CIcmp::SetTTL(int TTL){int Result;Result = setsockopt (icmpSocket, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int)); if (Result == SOCKET_ERROR){icmpSocketErrorMod = 1;icmpSocketError = WSAGetLastError(); }return Result;}6、Ping函数int CIcmp::Ping (LPSTR pIcmpBuffer, int DataLen){int Result;int IcmpBufferSize = DataLen + IcmpHeaderLength;pIcmpHeader = (LPIcmpHeader)pIcmpBuffer;memset (pIcmpBuffer, 'E', IcmpBufferSize);memset (pIcmpHeader, 0, IcmpHeaderLength);pIcmpHeader->IcmpType = ICMP_ECHO;pIcmpHeader->IcmpCode = 0;pIcmpHeader->IcmpChecksum = 0;pIcmpHeader->IcmpId = icmpCurId;pIcmpHeader->IcmpSeq = icmpCurSeq;pIcmpHeader->IcmpTimestamp = GetCurrentTime();pIcmpHeader->IcmpChecksum = IcmpChecksum ((USHORT FAR *)pIcmpBuffer,IcmpBufferSize); icmpPingSentAt = GetCurrentTime();Result = sendto (icmpSocket,pIcmpBuffer,IcmpBufferSize,0,(LPSOCKADDR)&icmpSockAddr,sizeof icmpSockAddr);if (Result == SOCKET_ERROR){ icmpSocketError = WSAGetLastError();icmpSocketErrorMod = 1;}return Result;}7、校验和函数unsigned short CIcmp::IcmpChecksum(unsigned short FAR *lpBuf, int Len) {register long ChkSum = 0L;while (Len > 1){ ChkSum += *(lpBuf++);Len -= sizeof (USHORT); }if (Len)ChkSum += *(UCHAR *)lpBuf;ChkSum = (ChkSum & 0xffff) + (ChkSum>>16);ChkSum += (ChkSum >> 16);#pragma warning(disable : 4244)return (~ChkSum);#pragma warning(default : 4244)}8、Receive函数int CIcmp::Receive(LPSTR pIcmpBuffer, int IcmpBufferSize) {LPSOCKADDR pRcvSockAddr = (LPSOCKADDR)&rcvSockAddr; int Result;int RcvIpHdrLen;icmpPingReceivedAt = GetTickCount();icmpCurId = 0;rcvSockAddr.sin_family = AF_INET;rcvSockAddr.sin_addr.s_addr = INADDR_ANY;rcvSockAddr.sin_port = 0;RcvIpHdrLen = sizeof rcvSockAddr;Result = recvfrom (icmpSocket,pIcmpBuffer,IcmpBufferSize,0,pRcvSockAddr,&RcvIpHdrLen);if (Result == SOCKET_ERROR){ icmpSocketError = WSAGetLastError();icmpSocketErrorMod = 1;DisplayError ("Receive","CIcmp::Receive");return Result;}icmpRcvLen = Result;pIpHeader = (LPIpHeader)pIcmpBuffer;RcvIpHdrLen = pIpHeader->HeaderLength * 4;if (Result < RcvIpHdrLen + ICMP_MIN){MessageBox(NULL,"Short message!","CIcmp::Receive",MB_OK|MB_SYSTEMMODAL);icmpSocketErrorMod = 2;return Result;}pIcmpHeader = (LPIcmpHeader)(pIcmpBuffer + RcvIpHdrLen);icmpCurId = pIcmpHeader->IcmpId;icmpRoundTripTime = icmpPingReceivedAt - pIcmpHeader->IcmpTimestamp;if (pIcmpHeader->IcmpType != ICMP_ECHOREPLY){return Result;}icmpCurSeq = pIcmpHeader->IcmpSeq;return Result;}五、运行结果用ping命令测试本地主机的ip地址六、心得体会通过本次课程设计,我感觉到自己在编程方面,能力还十分欠缺。