1、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选项函数流程图 83、源代码清单 84、心得体会 161、ping功能简介Ping 是DOS命令,一般用于检测网络通与不通 ,也叫时
2、延,其值越大,速度越慢PING (Packet Internet Grope),因特网包探索器,用于测试网络连接量的程序。Ping发送一个ICMP回声请求消息给目的地并报告是否收到所希望的ICMP回声应答。 它是用来检查网络是否通畅或者网络连接速度的命令。作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的:网络上的机器都有唯一确定的IP地址,我们给目标IP地址发送一个数据包,对方就要返回一个同样大小的数据包,根据返回的数据包我们可以确定目标主机的存在,可以初步判断目标主机的操作系统等。Ping 是Windows系列自带的一个可执行命令。利
3、用它可以检查网络是否能够连通,用好它可以很好地帮助我们分析判定网络故障。应用格式:Ping IP地址。该命令还可以加许多参数使用,具体是键入Ping按回车即可看到详细说明。ping指的是端对端连通,通常用来作为可用性的检查, 但是某些病毒木马会强行大量远程执行ping命令抢占你的网络资源,导致系统变慢,网速变慢。2、程序流程图 图1 main函数流程图图2创建套接字流程图图3 建立IP选项头部流程图图4 创建SockRaw套接字的接收/发送时限属性流程图图5判断终端的主机名获取信息流程图图6 分配堆内存流程图图7 接收/发送ICMP数据包流程图图8清空Socket库所占内存图9 传参解析函数流
4、程图i=0计算RR选项中记录的地址个数nii_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); /填充数据段/计
5、算检验和USHORT checksum(USHORT *buffer, int size) unsigned long cksum = 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);
6、/检验和取反,并返回/解析IP选项void DecodeIPOptions(char *buf, int bytes) IpOptionHeader *ipopt = NULL; IN_ADDR inaddr; /声明结构体 int i; HOSTENT *host = NULL; ipopt = (IpOptionHeader *)(buf + 20); /去掉IP首部,指针指向数据选项首部 printf(RR: ); for(i = 0; i ptr / 4) - 1; i+) inaddr.S_un.S_addr = ipopt-addri; if (i != 0) printf( );
7、 host = gethostbyaddr(char *)&inaddr.S_un.S_addr, sizeof(inaddr.S_un.S_addr), AF_INET);/通过IP地址获得主机信息 if (host) printf(%-15s) %sn, inet_ntoa(inaddr), host-h_name); /打印IP地址和主机名 else printf(%-15s)n, inet_ntoa(inaddr); /打印IP地址 return;/解析ICMP首部函数void DecodeICMPHeader(char *buf, int bytes, struct sockaddr
8、_in *from) IpHeader *iphdr = NULL; IcmpHeader *icmphdr = NULL; unsigned short iphdrlen; DWORD tick; /毫秒级数 static int icmpcount = 0; iphdr = (IpHeader *)buf; iphdrlen = iphdr-h_len * 4; /IP首部实际长度 tick = GetTickCount();/获得毫秒级数 if (iphdrlen = MAX_IP_HDR_SIZE) & (!icmpcount) /判断是否为一个IP数据包 DecodeIPOption
9、s(buf, bytes); /调用IP 选项解析函数 if (bytes sin_addr); icmphdr = (IcmpHeader*)(buf + iphdrlen); /指针指向ICMP报文首部 if (icmphdr-i_type != ICMP_ECHOREPLY) /判断ICMP类型是否为ICMP回显应答 printf(nonecho type %d recvdn, icmphdr-i_type); /输出其类型 return; if (icmphdr-i_id != (USHORT)GetCurrentProcessId()/获得当前进程的ID,判断是否为ICMP标识 pr
10、intf(someone elses packet!n); return ; printf(%d bytes from %s:, bytes, inet_ntoa(from-sin_addr); printf( icmp_seq = %d. , icmphdr-i_seq); /输出ICMP序列号 printf( time: %d ms, tick - icmphdr-timestamp); /打印时间戳 printf(n); icmpcount+; return;/传参解析函数void ValidateArgs(int argc, char *argv) int i; bRecordRout
11、e = FALSE;赋初值 lpdest = NULL; datasize = DEF_PACKET_SIZE; /初始化datasize,使其等于差错报文长度 for(i = 1; i h_addr, hp-h_length); dest.sin_family = hp-h_addrtype;将hp-h_addrtype的类型赋给dest.sin_family printf(dest.sin_addr = %sn, inet_ntoa(dest.sin_addr);/输出IP地址 else printf(gethostbyname() failed: %dn, WSAGetLastError
12、(); 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: %dn, GetLastError();/获得当前错误进程号,输出“堆内存分配失败” r
13、eturn -1; /退出main函数,并返回值-1 memset(icmp_data,0,MAX_PACKET);/填充数据段 FillICMPData(icmp_data,datasize);/调用ICMP 初始化函数 while(1) static int nCount = 0; /初始化 int bwrote; if (nCount+ = 4) break;结束整个循环 (IcmpHeader*)icmp_data)-i_cksum = 0; (IcmpHeader*)icmp_data)-timestamp = GetTickCount();/设定时间戳 (IcmpHeader*)i
14、cmp_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, (struct sockaddr*)&dest, sizeof(dest); /发送ICMP数据包 if (bwrote = SOCKET_ERROR) /发送失败 if (WSAGetLastError() = WSAETIM
15、EDOUT) /当前错误进程号为超时 printf(timed outn); continue; /结束本次循环 printf(sendto() failed: %dn, WSAGetLastError(); return -1; /退出main函数,并返回值-1 if (bwrote datasize)/已发送字节数小于datasize printf(Wrote %d bytesn, bwrote); bread = recvfrom(sockRaw, recvbuf, MAX_PACKET, 0, (struct sockaddr*)&from, &fromlen);/ 接收ICMP数据包 if (bread = SOCKET_ERROR) /接收失败 if (WSAGetLastEr
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1