实验3icmp协议实践ping解析.docx

上传人:b****7 文档编号:9103899 上传时间:2023-02-03 格式:DOCX 页数:11 大小:73.80KB
下载 相关 举报
实验3icmp协议实践ping解析.docx_第1页
第1页 / 共11页
实验3icmp协议实践ping解析.docx_第2页
第2页 / 共11页
实验3icmp协议实践ping解析.docx_第3页
第3页 / 共11页
实验3icmp协议实践ping解析.docx_第4页
第4页 / 共11页
实验3icmp协议实践ping解析.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

实验3icmp协议实践ping解析.docx

《实验3icmp协议实践ping解析.docx》由会员分享,可在线阅读,更多相关《实验3icmp协议实践ping解析.docx(11页珍藏版)》请在冰豆网上搜索。

实验3icmp协议实践ping解析.docx

实验3icmp协议实践ping解析

 

计算机网络实验上机指导书

 

专业

班级

学号

姓名

 

沈阳工程学院信息工程系

实验2ICMP协议实践--ping解析

一.实验目的

掌握ICMP原理,利用其实现网络主机状态测试。

二.实验内容

利用ICMP协议原理编程实现PING命令,测试目标主机是否可到达。

并了解Ping实现原理。

三.实验前的准备

了解ICMP原理及相关概念。

掌握相关软件编程知识。

四.实验要求及实验软硬件环境

【基本要求】

设计程序完成PING命令。

完成此项实验,完成实验报告。

【实验组织方式】

个人实验

【实验条件】

局域网环境下微机两台,编程软件。

五.实验步骤

六..了解ICMP原理以及网络编程

(1)源程序:

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<>

#include<>

#include

#include

#include

#include<>

#include

#include

#include

#include<>

#include<>

#include<>

#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->icmp_code=0;

icmp->icmp_cksum=0;

icmp->icmp_seq=pack_no;

icmp->icmp_id=pid;

packsize=8+datalen;

tval=(structtimeval*)icmp->icmp_data;

gettimeofday(tval,NULL);/*记录发送时间*/

icmp->icmp_cksum=cal_chksum((unsignedshort*)icmp,packsize);/*校验算法*/

returnpacksize;

}

/*发送三个ICMP报文*/

voidsend_packet()

{intpacketsize;

while(nsend

{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

{alarm(MAX_WAIT_TIME);

if((n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,

(structsockaddr*)&from,&fromlen))<0)

{if(errno==EINTR)continue;

perror("recvfromerror");

continue;

}

gettimeofday(&tvrecv,NULL);/*记录接收时间*/

if(unpack(recvpacket,n)==-1)continue;

nreceived++;

}

}

/*剥去ICMP报头*/

intunpack(char*buf,intlen)

{inti,iphdrlen;

structip*ip;

structicmp*icmp;

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->icmp_data;

tv_sub(&tvrecv,tvsend);/*接收和发送的时间差*/

rtt=*1000+1000;/*以毫秒为单位计算rtt*/

/*显示相关信息*/

printf("%dbytefrom%s:

icmp_seq=%uttl=%drtt=%.3fms\n",

len,

inet_ntoa,

icmp->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)

{printf("usage:

%shostname/IPaddress\n",argv[0]);

exit

(1);

}

if((protocol=getprotobyname("icmp"))==NULL)

{perror("getprotobyname");

exit

(1);

}

/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/

if((sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto))<0)

{perror("socketerror");

exit

(1);

}

/*回收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)/*是主机名*/

{perror("gethostbynameerror");

exit

(1);

}

memcpy((char*)&,host->h_addr,host->h_length);

}

else/*是ip地址*/

memcpy((char*)&dest_addr,(char*)&inaddr,host->h_length);

/*获取main的进程id,用于设置ICMP的标志符*/

pid=getpid();

printf("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)<0)

{--out->tv_sec;

out->tv_usec+=1000000;

}

out->tv_sec-=in->tv_sec;

}

/*-------------TheEnd-----------*/

运行结果如图6-2所示。

 

图6-2linux下运行ping程序

作业题:

1.阅读Ping程序

2.理解程序原理

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

当前位置:首页 > PPT模板 > 图表模板

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

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