ping程序分析报告.docx

上传人:b****5 文档编号:5043450 上传时间:2022-12-12 格式:DOCX 页数:19 大小:214.12KB
下载 相关 举报
ping程序分析报告.docx_第1页
第1页 / 共19页
ping程序分析报告.docx_第2页
第2页 / 共19页
ping程序分析报告.docx_第3页
第3页 / 共19页
ping程序分析报告.docx_第4页
第4页 / 共19页
ping程序分析报告.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

ping程序分析报告.docx

《ping程序分析报告.docx》由会员分享,可在线阅读,更多相关《ping程序分析报告.docx(19页珍藏版)》请在冰豆网上搜索。

ping程序分析报告.docx

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函数流程图

 

图2创建套接字流程图

 

 

图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",WSAGetLastError());

return-1;//退出main函数,并返回值-1

}

if(bwrote

{

printf("Wrote%dbytes\n",bwrote);

}

bread=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(structsockaddr*)&from,&fromlen);//接收ICMP数据包

if(bread==SOCKET_ERROR)//接收失败

{

if(WSAGetLastEr

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1