ping程序分析报告.docx
- 文档编号:11793632
- 上传时间:2023-04-02
- 格式:DOCX
- 页数:19
- 大小:177.07KB
ping程序分析报告.docx
《ping程序分析报告.docx》由会员分享,可在线阅读,更多相关《ping程序分析报告.docx(19页珍藏版)》请在冰豆网上搜索。
ping程序分析报告
ping程序分析报告
ping程序分析报告
课程名称:
老师:
姓名:
班级:
学号:
日期:
1、Ping功能简介…………………………………………………1
2、程序流程图
(1)主函数流程图…………………………………………………3
(2)创建套接字流程图……………………………………………3
(3)建立IP选项头部流程图……………………………………4
(4)创建SockRaw套接字的接收/发送时限属性流程图…………4
(5)判断终端的主机名获取信息流程图…………………………5
(6)分配堆内存流程图……………………………………………5
(7)接收/发送ICMP数据包流程图………………………………6
(8)清空Socket库所占内存……………………………………7
(9)传参解析函数流程图…………………………………………7
(10)解析IP选项函数流程图……………………………………8
3、源代码清单……………………………………………………8
4、心得体会………………………………………………………16
1、ping功能简介
Ping是DOS命令,一般用于检测网络通与不通,也叫时延,其值越大,速度越慢
PING(PacketInternetGrope),因特网包探索器,用于测试网络连接量的程序。
Ping发送一个ICMP回声请求消息给目的地并报告是否收到所希望的ICMP回声应答。
它是用来检查网络是否通畅或者网络连接速度的命令。
作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的:
网络上的机器都有唯一确定的IP地址,我们给目标IP地址发送一个数据包,对方就要返回一个同样大小的数据包,根据返回的数据包我们可以确定目标主机的存在,可以初步判断目标主机的操作系统等。
Ping是Windows系列自带的一个可执行命令。
利用它可以检查网络是否能够连通,用好它可以很好地帮助我们分析判定网络故障。
应用格式:
PingIP地址。
该命令还可以加许多参数使用,具体是键入Ping按回车即可看到详细说明。
ping指的是端对端连通,通常用来作为可用性的检查,
但是某些病毒木马会强行大量远程执行ping命令抢占你的网络资源,导致系统变慢,网速变慢。
2、程序流程图
图1main函数流程图
调用WSAStartup()函数请求版本信息
判断其返回值
返回值为0,即执行返回值为非0,即执行
失败成功
退出main函数,并返回一个值2调用传参解析函数
用socket函数创建一个套接口,设置属性
创建失败创建成功
退出main函数,并返回一个值3进入main函数步骤②
图2创建套接字流程图
bRecordRoute
TRUEFALSE
调用setsockopt()函数,并判断其返回值
返回值为返回值为一个进入main函数步骤
SOCKET_ERRORIP_OPTIONS③
的属性
获得当前错误的进程号,进入main函数步骤③
并输出错误信息
图3建立IP选项头部流程图
图4创建SockRaw套接字的接收/发送时限属性流程图
图5判断终端的主机名获取信息流程图
图6分配堆内存流程图
图7接收/发送ICMP数据包流程图
图8清空Socket库所占内存
图9传参解析函数流程图
i=0
计算RR选项中记录的地址个数n
i i! =0 NOYES 输出空格 通过IP地址获得主机信息 赋给host host 真假 输出主机名和地址输出地址 return i++ 图10解析IP首部函数流程图 3、源代码清单 //ModuleName: Ping.c #include"windows.h" #include"winsock.h" #include"stdio.h" #defineIP_RECORD_ROUTE0x7//IP记录路由 #defineICMP_ECHO8//ICMP回显 #defineICMP_ECHOREPLY0//ICMP回显应答 #defineICMP_MIN8//ICMP数据包最小长度 #defineDEF_PACKET_SIZE32//差错报文长度 #defineMAX_PACKET0x10000//ICMP包最大长度 #defineMAX_IP_HDR_SIZE60//IP首部最大字节数 //IP头文件定义 typedefstruct_iphdr { unsignedinth_len: 4;//头部长度4字节 unsignedintversion: 4;//IP版本号IPv4 unsignedchartos;//服务类型 unsignedshorttotal_len;//数据包总长度 unsignedshortident;//ID标识 unsignedshortfrag_and_flags;//3位标志,13位片偏移 unsignedcharttl;//生存期 unsignedcharproto;//协议类型 unsignedshortchecksum;//IP头部的检验和 unsignedintsourceIP;//源地址 unsignedintdestIP;//目的地址 }IpHeader; //ICMP头部定义 typedefstruct_icmphdr { BYTEi_type;//ICMP类型(8位) BYTEi_code;//代码类型(8位) USHORTi_cksum;//头部及数据检验和(16位) USHORTi_id;ID//标识 USHORTi_seq;//序列号 ULONGtimestamp;//时间戳 }IcmpHeader; //IP选项首部定义 typedefstruct_ipoptionhdr { unsignedcharcode;//IP选项的类型 unsignedcharlen;//RR选项总字节长度 unsignedcharptr;//指针字段 unsignedlongaddr[9];//IP地址清单 }IpOptionHeader; BOOLbRecordRoute; intdatasize; char*lpdest; //定义3个全局变量 //使用信息 voidusage(char*progname) { printf("usage: ping-r[datasize]\n"); printf("-rrecordroute\n"); printf("hostremotemachinetoping\n"); printf("datasizecanbeupto0x10000Byte\n"); ExitProcess(-1);//结束进程 } //ICMP首部初始化 voidFillICMPData(char*icmp_data,intdatasize) { IcmpHeader*icmp_hdr=NULL; char*datapart=NULL;//指针定义及初始化 icmp_hdr=(IcmpHeader*)icmp_data; icmp_hdr->i_type=ICMP_ECHO;//ICMP回显请求 icmp_hdr->i_code=0; icmp_hdr->i_id=(USHORT)GetCurrentProcessId();//取得当前进程号 icmp_hdr->i_cksum=0;//检验和字段置0 icmp_hdr->i_seq=0; datapart=icmp_data+sizeof(IcmpHeader);//datapart指针指向数据报文开头 memset(datapart,'E',datasize-sizeof(IcmpHeader));//填充数据段 } //计算检验和 USHORTchecksum(USHORT*buffer,intsize) { unsignedlongcksum=0;//检验和字段置0 while(size>1) { cksum+=*buffer++; size-=sizeof(USHORT); } if(size) { cksum+=*(UCHAR*)buffer; } cksum=(cksum>>16)+(cksum&0xffff);//将检验和字段高16位右移16位再与低16位相加 cksum+=(cksum>>16);//将所加的检验和再与剩余低16位相加 return(USHORT)(~cksum);//检验和取反,并返回 } //解析IP选项 voidDecodeIPOptions(char*buf,intbytes) { IpOptionHeader*ipopt=NULL; IN_ADDRinaddr;//声明结构体 inti; HOSTENT*host=NULL; ipopt=(IpOptionHeader*)(buf+20);//去掉IP首部,指针指向数据选项首部 printf("RR: "); for(i=0;i<(ipopt->ptr/4)-1;i++) { inaddr.S_un.S_addr=ipopt->addr[i]; if(i! =0) { printf(""); } host=gethostbyaddr((char*)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET);//通过IP地址获得主机信息 if(host) { printf("(%-15s)%s\n",inet_ntoa(inaddr),host->h_name); //打印IP地址和主机名 } else { printf("(%-15s)\n",inet_ntoa(inaddr));//打印IP地址 } } return; } //解析ICMP首部函数 voidDecodeICMPHeader(char*buf,intbytes,structsockaddr_in*from) { IpHeader*iphdr=NULL; IcmpHeader*icmphdr=NULL; unsignedshortiphdrlen; DWORDtick;//毫秒级数 staticinticmpcount=0; iphdr=(IpHeader*)buf; iphdrlen=iphdr->h_len*4;//IP首部实际长度 tick=GetTickCount();//获得毫秒级数 if((iphdrlen==MAX_IP_HDR_SIZE)&&(! icmpcount))//判断是否为一个IP数据包 { DecodeIPOptions(buf,bytes);//调用IP选项解析函数 } if(bytes { printf("Toofewbytesfrom%s\n", inet_ntoa(from->sin_addr)); } icmphdr=(IcmpHeader*)(buf+iphdrlen);//指针指向ICMP报文首部 if(icmphdr->i_type! =ICMP_ECHOREPLY)//判断ICMP类型是否为ICMP回显应答 { printf("nonechotype%drecvd\n",icmphdr->i_type);//输出其类型 return; } if(icmphdr->i_id! =(USHORT)GetCurrentProcessId())//获得当前进程的ID,判断是否为ICMP标识 { printf("someoneelse'spacket! \n"); return; } printf("%dbytesfrom%s: ",bytes,inet_ntoa(from->sin_addr)); printf("icmp_seq=%d.",icmphdr->i_seq);//输出ICMP序列号 printf("time: %dms",tick-icmphdr->timestamp);//打印时间戳 printf("\n"); icmpcount++; return; } //传参解析函数 voidValidateArgs(intargc,char**argv) { inti; bRecordRoute=FALSE;赋初值 lpdest=NULL; datasize=DEF_PACKET_SIZE;//初始化datasize,使其等于差错报文长度 for(i=1;i { if((argv[i][0]=='-')||(argv[i][0]=='/'))//判断数组argv第i行第0列是否为‘-’或‘/’ { switch(tolower(argv[i][1]))//将数组argv第i行第1列的字符转化为小写字母 { case'r': //记录路由选项 bRecordRoute=TRUE; break; default: usage(argv[0]);调用usage函数 break; } } elseif(isdigit(argv[i][0]))//判断数组argv第i行第0列是否为数字 { datasize=atoi(argv[i]);//将数组argv第i行的字符转化成长整型数 } else { lpdest=argv[i]; } } } //main函数 intmain(intargc,char**argv)//argc代表命令行中的参数个数,**argv是指向字符串的指针 { char*icmp_data=NULL; char*recvbuf=NULL; USHORTseq_no=0; //定义及初始化 structsockaddr_indest={'\0'}; structsockaddr_infrom={'\0'}; structhostent*hp=NULL; //声明结构体 intbread=0; intret=0; intfromlen=sizeof(from); inttimeout=1000; unsignedintaddr=0; //定义及初始化 WSADATAwsaData;//声明数据结构 SOCKETsockRaw=INVALID_SOCKET; IpOptionHeaderipopt={'\0'}; if(WSAStartup(MAKEWORD(2,2),&wsaData)! =0)//指明程序请求使用的socket版本,返回请求的版本信息 { printf("WSAStartup()failed: %d\n",GetLastError());//获得当前的进程错误号,并输出“请求版本信息失败” return2; } ValidateArgs(argc,argv);//调用传参解析函数 sockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);//创建sockRaw套接字 if(sockRaw==INVALID_SOCKET)//创建失败 { printf("WSASocket()failed: %d\n",WSAGetLastError()); return3;//返回值3,并退出main函数 } if(bRecordRoute) { ZeroMemory(&ipopt,sizeof(ipopt)); ipopt.code=IP_RECORD_ROUTE; ipopt.ptr=4;//指向第一个地址列表 ipopt.len=39; ret=setsockopt(sockRaw,IPPROTO_IP,IP_OPTIONS, (char*)&ipopt,sizeof(ipopt));//设置sockRaw套接字属性 if(ret==SOCKET_ERROR)//设置属性失败 { printf("setsockopt(IP_OPTIONS)failed: %d\n", WSAGetLastError());//取得当前错误进程号,并输出“属性设置失败” } } bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO, (char*)&timeout,sizeof(timeout));//设置套接字接收时限属性 if(bread==SOCKET_ERROR)//设置失败 { printf("setsockopt(SO_RCVTIMEO)failed: %d\n", WSAGetLastError()); return-1;返回值-1,并退出main函数 } timeout=1000; bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO, (char*)&timeout,sizeof(timeout));//设置套接字发送时限属性 if(bread==SOCKET_ERROR)//设置发送时限失败 { printf("setsockopt(SO_SNDTIMEO)failed: %d\n", WSAGetLastError()); return-1;返回值-1,并退出main函数 } memset(&dest,0,sizeof(dest));//填充数据段, dest.sin_family=AF_INET;//指定地址族 if((dest.sin_addr.s_addr=inet_addr(lpdest))==INADDR_NONE) //网络地址是无效的地址 { if((hp=gethostbyname(lpdest))! =NULL) { memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length); dest.sin_family=hp->h_addrtype;将hp->h_addrtype的类型赋给dest.sin_family printf("dest.sin_addr=%s\n",inet_ntoa(dest.sin_addr));//输出IP地址 } else { printf("gethostbyname()failed: %d\n", WSAGetLastError()); return-1;退出main函数,并返回值-1 } } datasize+=sizeof(IcmpHeader); icmp_data=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);//分配堆内存 recvbuf=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET); if(! icmp_data)//分配失败 { printf("HeapAlloc()failed: %d\n",GetLastError());//获得当前错误进程号,输出“堆内存分配失败” return-1;//退出main函数,并返回值-1 } memset(icmp_data,0,MAX_PACKET);//填充数据段 FillICMPData(icmp_data,datasize);//调用ICMP初始化函数 while (1) { staticintnCount=0;//初始化 intbwrote; if(nCount++==4) { break;结束整个循环 } ((IcmpHeader*)icmp_data)->i_cksum=0; ((IcmpHeader*)icmp_data)->timestamp=GetTickCount();//设定时间戳 ((IcmpHeader*)icmp_data)->i_seq=seq_no++;//设置ICMP头部序列号 ((IcmpHeader*)icmp_data)->i_cksum= checksum((USHORT*)icmp_data,datasize);//调用计算检验和函数,将其返回值赋给i_cksum bwrote=sendto(sockRaw,icmp_data,datasize,0, (structsockaddr*)&dest,sizeof(dest));//发送ICMP数据包 if(bwrote==SOCKET_ERROR)//发送失败 { if(WSAGetLastError()==WSAETIMEDOUT)//当前错误进程号为超时 { printf("timedout\n"); continue;//结束本次循环 } printf("sendto()failed: %d\n",WSAGe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ping 程序 分析 报告