ping程序分析报告Word下载.docx
- 文档编号:17998999
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:19
- 大小:214.12KB
ping程序分析报告Word下载.docx
《ping程序分析报告Word下载.docx》由会员分享,可在线阅读,更多相关《ping程序分析报告Word下载.docx(19页珍藏版)》请在冰豆网上搜索。
图6分配堆内存流程图
图7接收/发送ICMP数据包流程图
图8清空Socket库所占内存
图9传参解析函数流程图
i=0
计算RR选项中记录的地址个数n
i<
n
i!
=0
NOYES
输出空格
通过IP地址获得主机信息
赋给host
host
真假
输出主机名和地址输出地址
return
i++
图10解析IP首部函数流程图
3、源代码清单
//ModuleName:
Ping.c
#include"
windows.h"
winsock.h"
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:
//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"
);
-rrecordroute\n"
hostremotemachinetoping\n"
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回显请求
i_code=0;
i_id=(USHORT)GetCurrentProcessId();
//取得当前进程号
i_cksum=0;
//检验和字段置0
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首部,指针指向数据选项首部
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)
(%-15s)%s\n"
inet_ntoa(inaddr),host->
h_name);
//打印IP地址和主机名
else
(%-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<
iphdrlen+ICMP_MIN)判断IP数据包长度
{
printf("
Toofewbytesfrom%s\n"
inet_ntoa(from->
sin_addr));
icmphdr=(IcmpHeader*)(buf+iphdrlen);
//指针指向ICMP报文首部
if(icmphdr->
i_type!
=ICMP_ECHOREPLY)//判断ICMP类型是否为ICMP回显应答
nonechotype%drecvd\n"
icmphdr->
i_type);
//输出其类型
return;
i_id!
=(USHORT)GetCurrentProcessId())//获得当前进程的ID,判断是否为ICMP标识
someoneelse'
spacket!
\n"
return;
%dbytesfrom%s:
"
bytes,inet_ntoa(from->
icmp_seq=%d."
i_seq);
//输出ICMP序列号
time:
%dms"
tick-icmphdr->
timestamp);
//打印时间戳
icmpcount++;
//传参解析函数
voidValidateArgs(intargc,char**argv)
bRecordRoute=FALSE;
赋初值
lpdest=NULL;
datasize=DEF_PACKET_SIZE;
//初始化datasize,使其等于差错报文长度
for(i=1;
argc;
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函数
}
elseif(isdigit(argv[i][0]))//判断数组argv第i行第0列是否为数字
datasize=atoi(argv[i]);
//将数组argv第i行的字符转化成长整型数
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={'
structhostent*hp=NULL;
//声明结构体
intbread=0;
intret=0;
intfromlen=sizeof(from);
inttimeout=1000;
unsignedintaddr=0;
WSADATAwsaData;
//声明数据结构
SOCKETsockRaw=INVALID_SOCKET;
IpOptionHeaderipopt={'
if(WSAStartup(MAKEWORD(2,2),&
wsaData)!
=0)//指明程序请求使用的socket版本,返回请求的版本信息
WSAStartup()failed:
%d\n"
GetLastError());
//获得当前的进程错误号,并输出“请求版本信息失败”
return2;
ValidateArgs(argc,argv);
//调用传参解析函数
sockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
//创建sockRaw套接字
if(sockRaw==INVALID_SOCKET)//创建失败
WSASocket()failed:
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*)&
//设置sockRaw套接字属性
if(ret==SOCKET_ERROR)//设置属性失败
setsockopt(IP_OPTIONS)failed:
WSAGetLastError());
//取得当前错误进程号,并输出“属性设置失败”
bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,
(char*)&
timeout,sizeof(timeout));
//设置套接字接收时限属性
if(bread==SOCKET_ERROR)//设置失败
setsockopt(SO_RCVTIMEO)failed:
WSAGetLastError());
return-1;
返回值-1,并退出main函数
timeout=1000;
bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,
(char*)&
//设置套接字发送时限属性
if(bread==SOCKET_ERROR)//设置发送时限失败
setsockopt(SO_SNDTIMEO)failed:
返回值-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
dest.sin_addr=%s\n"
inet_ntoa(dest.sin_addr));
//输出IP地址
gethostbyname()failed:
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)//分配失败
HeapAlloc()failed:
//获得当前错误进程号,输出“堆内存分配失败”
//退出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)->
timestamp=GetTickCount();
//设定时间戳
i_seq=seq_no++;
//设置ICMP头部序列号
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;
//结束本次循环
sendto()failed:
if(bwrote<
datasize)//已发送字节数小于datasize
Wrote%dbytes\n"
bwrote);
bread=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(structsockaddr*)&
from,&
fromlen);
//接收ICMP数据包
if(bread==SOCKET_ERROR)//接收失败
if(WSAGetLastEr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ping 程序 分析 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)