您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > c++实现ping功能
综合课程设计报告第1页共19页题目:VC++实现探测远程主机是否可达1课程设计目的(1)了解探测远程主机是否可达的方法。(2)了解windows网络编程的基本步骤。(3)了解TCP/IP协议及ICMP协议。(4)掌握ping命令的思想。(5)掌握WindowsSocketAPI的使用方法。2课程设计原理ICMP:互联网控制报文协议,提供一个特殊的报文在互联网的结点之间进行监测和控制,测试目的主机是否可达,与本次课程设计目的一致,因此可模拟ICMP的工作方式来编制程序。首先通过生成一个ICMP“回应请求”,然后将其定向至打算查询的目标主机,远程主机会拦截这个请求,然后生成一条回应答复消息,再通过网络回传给我们。若是不能抵达目标主机,则会生成相应的错误消息。具体步骤如下:1)创建类型为SOCK_RAW的一个套接字,同时设定协议IPPROTO_ICMP。2)创建并初始化ICMP头。3)调用sendto将ICMP请求发给远程主机。4)调用recvfrom以接收ICMP响应。其流程图如下:综合课程设计报告第2页共19页开始启动Winsock获取关键参数:目的主机地址创建套接字,协议字段:ICMP设置发送和接收数据最长等待时间timeout填写目的主机信息建立ICMP数据包inti=0发送和接收数据包一次,i++i4?释放内存,关闭Winsock结束是否3程序源代码及运行结果3.1源代码#includewinsock2.h#includeiostream.h#pragmacomment(lib,ws2_32.lib)综合课程设计报告第3页共19页#defineICMP_ECHO8//回应请求类型的ICMP消息类型#defineICMP_ECHOREPLY0//回应答复型的ICMP消息类型#defineICMP_MIN8//ICMP数据报最小长度#defineDEF_PACKET_SIZE32//默认数据报大小#defineDEF_PACKET_NUMBER4//发送数据报的个数#defineMAX_PACKET1024//最大ICMP数据报大小char*Ipdest;//目标主机的IP地址intdatasize;//ICMP消息的长度//接收到的ICMP消息数,每收到一条ICMP消息就加1staticinticmpcount=0;//IP头(20字节)structIPHEAD{unsignedintheadlength:4;//4位头长度unsignedintversion:4;//4位版本unsignedchartos;//8位服务类型unsignedshorttotallength;//16位总长unsignedshortip_id;//16位标识unsignedshortfrag_and_flags;//3个一位标识加分段偏移unsignedcharttl;//8位存活时间unsignedcharprotocal;//8位协议类型unsignedshortip_checksum;//16位头校验和unsignedintsourceIP;//32位源IP地址unsignedintdestIP;//32位目标IP地址};综合课程设计报告第4页共19页//ICMP头(12字节)structICMPHEAD{unsignedchartype;//类型(0,8)unsignedcharcode;//代码(0)unsignedshorticmp_checksum;//校验和unsignedshorticmp_id;//标识符unsignedshortseq;//序号unsignedlongtimestamp;//时间戳};//Fill_icmp_data函数:用于设置ICMP头部,填充ICMP消息voidFill_icmp_data(char*icmp_data,intdatasize){ICMPHEAD*icmphead=NULL;char*datapart=NULL;icmphead=(ICMPHEAD*)icmp_data;icmphead-type=ICMP_ECHO;//ICMP_ECHO=8icmphead-code=0;//类型为8,代码为0,表示回应请求icmphead-icmp_checksum=0;icmphead-icmp_id=(unsignedshort)GetCurrentProcessId();datapart=icmp_data+sizeof(ICMPHEAD);//具体内容的首地址指针//初始化数据包内容部分for(inti=0;i(datasize-sizeof(ICMPHEAD));i++,datapart++)*datapart=0;}综合课程设计报告第5页共19页//DecodeICMPHEAD函数:接受数据时从IP头中获取ICMP消息voidDecodeICMPHEAD(char*recvbuf,intbread,sockaddr_in*from){IPHEAD*iphead=NULL;ICMPHEAD*icmphead=NULL;DWORDtick;unsignedshortiphdrlen;iphead=(IPHEAD*)recvbuf;//32位字的个数乘以4即字节个数iphdrlen=(iphead-headlength)*4;//获取操作系统启动至今所经过的时间(ms)tick=GetTickCount();if(bread(iphdrlen+ICMP_MIN)){coutToofewbytesfrom:inet_ntoa(from-sin_addr);coutendl;}icmphead=(ICMPHEAD*)(recvbuf+iphdrlen);//ICMP消息始于IP头之后//若ICMP消息类型并非查询,则输出相应信息类型if(icmphead-type!=ICMP_ECHOREPLY){coutnonechotypeint(icmphead-type)received;coutendl;}综合课程设计报告第6页共19页//确认收到的应答ICMP消息是否是对发送出去的消息的回应//若其表示与当前进程不符,则输出出错信息if(icmphead-icmp_id!=(unsignedshort)GetCurrentProcessId()){coutIt'ssomeoneelse'spacket!endl;return;}//输出收到信息的内容:主机地址,icmp消息序号,回应时间,存活时间coutReplyfrominet_ntoa(from-sin_addr);coutbytes=bread-iphdrlen;couttime:GetTickCount()-icmphead-timestampms;coutseq=icmphead-seq;coutendl;icmpcount++;}//Checksum函数:用于求ICMP首部校验和unsignedshortChecksum(unsignedshort*buffer,intsize){unsignedlongcksum=0;//设校验和初值为0while(size1){cksum+=*buffer++;//求各个16位数字之和size-=sizeof(unsignedshort);}if(size){综合课程设计报告第7页共19页cksum+=*(unsignedchar*)buffer;}cksum=(cksum16)+(cksum&0xffff);//高位与低位相加cksum+=(cksum16);//加上进位return(unsignedshort)(~cksum);//取反得到校验和}//Usage函数:表示程序的功能voidUsage(char*progname){coutUsage:prognamehostendl;couthostremotemachinetoPingendl;coutendl;}//ValidateArgs函数:用于给目的地址和数据包大小赋值voidValidateArgs(intargc,char**argv){datasize=DEF_PACKET_SIZE;//数据包大小为DEF_PACKET_SIZE=32if(argc2){Usage(argv[0]);//只输入一个参数:程序名Ipdest=202.119.81.120;//默认目的地址为:202.119.81.120}elseif(argc==2)Ipdest=argv[1];//第二个参数为目的地址}综合课程设计报告第8页共19页//main函数:进行建立套接字,创建ICMP头,设置超时时间,发送和接受数据等。intmain(intargc,char**argv){WSADATAwsaData;SOCKETsockRaw=INVALID_SOCKET;sockaddr_indest,from;intdestlen=sizeof(dest),fromlen=sizeof(from),bwrote,bread;char*icmp_data=NULL,*recvbuf=NULL;structhostent*hp=NULL;unsignedshortseq=0;//启动winsock失败,输出错误提示信息if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0){coutWSAStartupfailed:GetLastError();coutendl;return-1;}ValidateArgs(argc,argv);//创建套接字失败,输出错误信息提示sockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);if(sockRaw==INVALID_SOCKET)综合课程设计报告第9页共19页{coutWSASocket()failed:GetLastError();coutendl;return-1;}//设定发送数据时最长等待时间timeout=1000msinttimeout=1000;bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));if(bread==SOCKET_ERROR){coutsetsockopt(SO_RCVTIMEO)failed:WSAGetLastError();coutendl;return-1;}//设定接收数据时最长等待时间timeout=1000mstimeout=1000;bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));if(bread==SOCKET_ERROR){coutsetsockopt(SO_SNDTIMEO)failed:WSAGetLastError();coutendl;return-1;}综合课程设计报告第10页共19页//解析目的地址的名称dest.sin_family=AF_INET;if(dest.sin_addr.s_addr=inet_addr(Ipdest)){//inet_addr将IP地址转换成网络地址if((hp=gethostbyname(Ipdest))!=NULL){//gethostbyname主机信息memcpy(&(dest.sin_addr),hp-h_addr,hp-h_length);//复制内存dest.sin_family=hp-h_addrtype;coutdest.sin_addr=
本文标题:c++实现ping功能
链接地址:https://www.777doc.com/doc-5859018 .html