实验3icmp协议实践ping解析Word文件下载.docx
- 文档编号:22240022
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:11
- 大小:73.80KB
实验3icmp协议实践ping解析Word文件下载.docx
《实验3icmp协议实践ping解析Word文件下载.docx》由会员分享,可在线阅读,更多相关《实验3icmp协议实践ping解析Word文件下载.docx(11页珍藏版)》请在冰豆网上搜索。
Windows
PingPingPingPingPingPingS.ArmyBallisticResearchLaboratory
*/
while(nleft>
1){
sum+=*w++;
nleft-=2;
}
/*mopupanoddbyte,ifnecessary*/
if(nleft==1){
u_shortu=0;
*(u_char*)(&
u)=*(u_char*)w;
sum+=u;
/*
*addbackcarryoutsfromtop16bitstolow16bits
sum=(sum>
>
16)+(sum&
0xffff);
/*addhi16tolow16*/
sum+=(sum>
16);
/*addcarry*/
answer=~sum;
/*truncateto16bits*/
return(answer);
}
实验结果如图6-1所示。
图6-1ping程序运行结果
(2)LINUX
/*简单的ping程序*/
#include<
arpa/>
sys/>
netinet/>
#definePACKET_SIZE4096
#defineMAX_WAIT_TIME5
#defineMAX_NO_PACKETS3
charsendpacket[PACKET_SIZE];
charrecvpacket[PACKET_SIZE];
intsockfd,datalen=56;
intnsend=0,nreceived=0;
structsockaddr_indest_addr;
pid_tpid;
structsockaddr_infrom;
structtimevaltvrecv;
voidstatistics(intsigno);
unsignedshortcal_chksum(unsignedshort*addr,intlen);
intpack(intpack_no);
voidsend_packet(void);
voidrecv_packet(void);
intunpack(char*buf,intlen);
voidtv_sub(structtimeval*out,structtimeval*in);
voidstatistics(intsigno)
{printf("
\n--------------------PINGstatistics-------------------\n"
);
printf("
%dpacketstransmitted,%dreceived,%%%dlost\n"
nsend,nreceived,
(nsend-nreceived)/nsend*100);
close(sockfd);
exit
(1);
/*校验和算法*/
unsignedshortcal_chksum(unsignedshort*addr,intlen)
{intnleft=len;
intsum=0;
unsignedshort*w=addr;
unsignedshortanswer=0;
/*把ICMP报头二进制数据以2字节为单位累加起来*/
while(nleft>
1)
{sum+=*w++;
nleft-=2;
/*若ICMP报头为奇数个字节,会剩下最后一字节。
把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/
if(nleft==1)
{*(unsignedchar*)(&
answer)=*(unsignedchar*)w;
sum+=answer;
sum=(sum>
16)+(sum&
0xffff);
sum+=(sum>
16);
answer=~sum;
returnanswer;
/*设置ICMP报头*/
intpack(intpack_no)
{inti,packsize;
structicmp*icmp;
structtimeval*tval;
icmp=(structicmp*)sendpacket;
icmp->
icmp_type=ICMP_ECHO;
icmp_code=0;
icmp_cksum=0;
icmp_seq=pack_no;
icmp_id=pid;
packsize=8+datalen;
tval=(structtimeval*)icmp->
icmp_data;
gettimeofday(tval,NULL);
/*记录发送时间*/
icmp_cksum=cal_chksum((unsignedshort*)icmp,packsize);
/*校验算法*/
returnpacksize;
/*发送三个ICMP报文*/
voidsend_packet()
{intpacketsize;
while(nsend<
MAX_NO_PACKETS)
{nsend++;
packetsize=pack(nsend);
/*设置ICMP报头*/
if(sendto(sockfd,sendpacket,packetsize,0,
(structsockaddr*)&
dest_addr,sizeof(dest_addr))<
0)
{perror("
sendtoerror"
continue;
sleep
(1);
/*每隔一秒发送一个ICMP报文*/
/*接收所有ICMP报文*/
voidrecv_packet()
{intn,fromlen;
externinterrno;
signal(SIGALRM,statistics);
fromlen=sizeof(from);
while(nreceived<
nsend)
{alarm(MAX_WAIT_TIME);
if((n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,
from,&
fromlen))<
0)
{if(errno==EINTR)continue;
perror("
recvfromerror"
gettimeofday(&
tvrecv,NULL);
/*记录接收时间*/
if(unpack(recvpacket,n)==-1)continue;
nreceived++;
/*剥去ICMP报头*/
intunpack(char*buf,intlen)
{inti,iphdrlen;
structip*ip;
structtimeval*tvsend;
doublertt;
ip=(structip*)buf;
iphdrlen=ip->
ip_hl<
<
2;
/*求ip报头长度,即ip报头的长度标志乘4*/
icmp=(structicmp*)(buf+iphdrlen);
/*越过ip报头,指向ICMP报头*/
len-=iphdrlen;
/*ICMP报头及ICMP数据报的总长度*/
if(len<
8)/*小于ICMP报头长度则不合理*/
{printf("
ICMPpackets\'
slengthislessthan8\n"
return-1;
/*确保所接收的是我所发的的ICMP的回应*/
if((icmp->
icmp_type==ICMP_ECHOREPLY)&
&
(icmp->
icmp_id==pid))
{tvsend=(structtimeval*)icmp->
tv_sub(&
tvrecv,tvsend);
/*接收和发送的时间差*/
rtt=*1000+1000;
/*以毫秒为单位计算rtt*/
/*显示相关信息*/
%dbytefrom%s:
icmp_seq=%uttl=%drtt=%.3fms\n"
len,
inet_ntoa,
icmp_seq,
ip->
ip_ttl,
rtt);
elsereturn-1;
main(intargc,char*argv[])
{structhostent*host;
structprotoent*protocol;
unsignedlonginaddr=0l;
intwaittime=MAX_WAIT_TIME;
intsize=50*1024;
if(argc<
2)
usage:
%shostname/IPaddress\n"
argv[0]);
if((protocol=getprotobyname("
icmp"
))==NULL)
getprotobyname"
/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/
if((sockfd=socket(AF_INET,SOCK_RAW,protocol->
p_proto))<
socketerror"
/*回收root权限,设置当前用户权限*/
setuid(getuid());
/*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&
size,sizeof(size));
bzero(&
dest_addr,sizeof(dest_addr));
=AF_INET;
/*判断是主机名还是ip地址*/
if(inaddr=inet_addr(argv[1])==INADDR_NONE)
{if((host=gethostbyname(argv[1]))==NULL)/*是主机名*/
gethostbynameerror"
memcpy((char*)&
host->
h_addr,host->
h_length);
else/*是ip地址*/
dest_addr,(char*)&
inaddr,host->
/*获取main的进程id,用于设置ICMP的标志符*/
pid=getpid();
PING%s(%s):
%dbytesdatainICMPpackets.\n"
argv[1],
inet_ntoa,datalen);
send_packet();
/*发送所有ICMP报文*/
recv_packet();
/*接收所有ICMP报文*/
statistics(SIGALRM);
/*进行统计*/
return0;
/*两个timeval结构相减*/
voidtv_sub(structtimeval*out,structtimeval*in)
{if((out->
tv_usec-=in->
tv_usec)<
{--out->
tv_sec;
out->
tv_usec+=1000000;
tv_sec-=in->
/*-------------TheEnd-----------*/
运行结果如图6-2所示。
图6-2linux下运行ping程序
作业题:
1.阅读Ping程序
2.理解程序原理
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 icmp 协议 实践 ping 解析
![提示](https://static.bdocx.com/images/bang_tan.gif)