ping实验报告.docx
《ping实验报告.docx》由会员分享,可在线阅读,更多相关《ping实验报告.docx(11页珍藏版)》请在冰豆网上搜索。
ping实验报告
沈阳工程学院
学生实验报告
实验室名称:
信息工程系软件实验室
实验课程名称:
计算机网络
实验项目名称:
ICMP协议应用——Ping解析
班级:
姓名:
学号:
实验日期:
2012年04月28日实验台编号:
23
指导教师:
批阅教师(签字):
成绩:
一.实验目的
1)掌握ICMP原理,体会网络层编程的不同;
2)理解ICMP报文的作用,了解基本的网络编程框架。
二.实验内容
1)解析Ping程序的基本实现过程。
2)体会ICMP协议在Ping程序中的应用。
3)体会基本的C/S编程框架。
三.实验前的准备
1)掌握ICMP原理及相关概念。
2)掌握C语言编程知识。
3)掌握基本的网络编程内容
四.实验要求及实验软硬件环境
【基本要求】
对Ping程序进行调试并运行实现。
解析ping程序的主要部分,从而体会ICMP协议的应用。
完成此项实验,完成实验报告。
【实验组织方式】
小组实验
【实验条件】
局域网环境下微机二台,编程软件。
五.实验步骤
1.熟悉IP以及ICMP协议的工作机制;
2.熟悉创建原始套接字、IP报头和ICMP报头;
3.体会ICMP协议的作用与特点;
4.调试ICMP协议的Ping实现程序;
5.参加答辩,并撰写实验报告
六.主要程序部分(C++语言实现)
//ping.cpp:
定义控制台应用程序的入口点。
#include
#include
#include
#defineSEND_SIZE32
#definePACKET_SIZE4096
#defineICMP_ECHO8
#defineICMP_ECHOREPLY0
#pragmacomment(lib,"Ws2_32.lib")
structicmp
{
unsignedcharicmp_type;
//类型
unsignedcharicmp_code;
//编码
unsignedshorticmp_chksum;
//校验和
unsignedshorticmp_id;
//标示符
unsignedshorticmp_seq;
//顺序号
unsignedlongicmp_data;
//数据
};
structip
{
unsignedcharip_hl:
4;
//报头长度
unsignedcharip_v:
4;
//版本号
unsignedcharip_tos;
//服务类型
unsignedshortip_len;
//总长度
unsignedshortip_id;
//标识
unsignedshortip_off;
//标志
unsignedcharip_ttl;
//生存时间
unsignedcharip_p;
//协议号
unsignedshortip_sum;
//报头校验和
unsignedlongip_src;
//源IP地址
unsignedlongip_dst;
//目的IP地址
};
charsendpacket[PACKET_SIZE];
charrecvpacket[PACKET_SIZE];
structsockaddr_indest_addr;
structsockaddr_infrom_addr;
intsockfd;
intpid;
unsignedshortcal_chksum(unsignedshort*addr,intlen);
intpack(intpack_no);
intunpack(unsignedchar*buf,intlen);
voidsend_packet(void);
voidrecv_packet(void);
intmain(intargc,CHAR*argv[])
{
structhostent*host;
structprotoent*protocol;
inttimeout=1000;
intSEND_COUNT=4;
inti;
char*par_host;
charm_Input[100];
printf("InputIP:
");
gets(m_Input);
par_host=m_Input;
WORDwVersionRequested;
WSADATAwsaData;
interr;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested,&wsaData);
if(err!
=0)return;
if(LOBYTE(wsaData.wVersion)!
=2||
HIBYTE(wsaData.wVersion)!
=2){
WSACleanup();
return;
}
if((protocol=getprotobyname("icmp"))==NULL)//返回对应于给定协议名的包含名字和协议号
{
printf("getprotobynameerror\n");//的protoent结构指针
exit
(1);
}
if((sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto))<0)
{
printf("socketerror\n");
exit
(1);
}
if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout))<0)//设置套接口的选项
fprintf(stderr,"failedtosetrecvtimeout:
%d\n",WSAGetLastError());
if(setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout))<0)
fprintf(stderr,"failedtosetsendtimeout:
%d\n",WSAGetLastError());
memset(&dest_addr,0,sizeof(dest_addr));
dest_addr.sin_family=AF_INET;
if(host=gethostbyname(par_host))//返回对应于给定主机名的主机信息
{
memcpy((char*)&dest_addr.sin_addr,host->h_addr,host->h_length);
//resolveaddresstohostname
if(host=gethostbyaddr(host->h_addr,4,PF_INET))
par_host=host->h_name;
}
elseif(dest_addr.sin_addr.s_addr=inet_addr(par_host)==INADDR_NONE)
{
printf("Unkownhost%s\n",par_host);
exit
(1);
}
pid=_getpid();
printf("Pinging%s[%s]:
with%dbytesofdata:
\n\n",par_host,inet_ntoa(dest_addr.sin_addr),SEND_SIZE);
for(i=0;i{
send_packet();
recv_packet();
Sleep(1000);
}
}
//thisalgorithmisreferencedfromother's
unsignedshortcal_chksum(unsignedshort*addr,intlen)
{
intnleft=len;
intsum=0;
unsignedshort*w=addr;
unsignedshortanswer=0;
while(nleft>1)
{sum+=*w++;
nleft-=2;
}
if(nleft==1)//处理ICMP报头为奇数个字节时累加最后一个
{*(unsignedchar*)(&answer)=*(unsignedchar*)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
returnanswer;
}
//打包
intpack(intpack_no)
{
intpacksize;
structicmp*icmp;
packsize=8+SEND_SIZE;
icmp=(structicmp*)sendpacket;
icmp->icmp_type=ICMP_ECHO;
icmp->icmp_code=0;
icmp->icmp_chksum=0;
icmp->icmp_seq=pack_no;
icmp->icmp_id=pid;
icmp->icmp_data=GetTickCount();
icmp->icmp_chksum=cal_chksum((unsignedshort*)icmp,packsize);/*校验算法*/
returnpacksize;
}
//解包
intunpack(char*buf,intlen)
{
structip*ip;
structicmp*icmp;
doublertt;
intiphdrlen;
ip=(structip*)buf;
iphdrlen=ip->ip_hl*4;
icmp=(structicmp*)(buf+iphdrlen);
if((icmp->icmp_type==ICMP_ECHOREPLY)&&(icmp->icmp_id==pid))
{
len=len-iphdrlen-8;
rtt=GetTickCount()-icmp->icmp_data;
printf("Replyfrom%s:
bytes=%dtime=%.0fmsTTL=%dicmp_seq=%u\n",
inet_ntoa(from_addr.sin_addr),
len,
rtt,
ip->ip_ttl,
icmp->icmp_seq);
return1;
}
return0;
}
//发送
voidsend_packet()
{
intpacketsize;
staticintpack_no=0;
packetsize=pack(pack_no++);
if(sendto(sockfd,sendpacket,packetsize,0,(structsockaddr*)&dest_addr,sizeof(dest_addr))<0)
printf("Destinationhostunreachable.\n");
//printf("sendNO%d\n",pack_no-1);
}
//接收
voidrecv_packet()
{
intn,fromlen;
intsuccess;
fromlen=sizeof(from_addr);
do
{
if((n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,(structsockaddr*)&from_addr,&fromlen))>=0)
success=unpack(recvpacket,n);
elseif(WSAGetLastError()==WSAETIMEDOUT)
{
printf("Requesttimedout.\n");
return;
}
}while(!
success);
}
七.结果分析
运行结果如图1所示:
图1运行结果
运行结果可看出此程序不断地在向172.20.72.12发送数据包,并且得到了应答。
八.个人总结
本次课程设计较好地实现了要求做到的功能,但同时也遇到不少的困难和挑战。
通过本次实验我们了解到ICMP协议是一个非常重要的协议,它对于网络安全、网络的正常运作具有极其重要的意义,它被用于在IP主机、路由器之间传递控制消息,如网络通不通、主机是否可达、路由是否可用等。
实验中将原始数据在网络层添加IP报头和数据链路层添加ICMP的报头,再在目的端解封装这两个报头。
通过这次实验,我们不但加深了对Socket的原始套接字RAW编程的理解,同时也对IP和ICMP协议有了进一步的认识。
教
师
评
语
教师签字:
年月日