admin管理员组文章数量:1530919
2023年12月22日发(作者:)
沈 阳 工 程 学 院
学 生 实 验 报 告
实验室名称:信息工程系软件实验室
实验课程名称:计算机网络
实验项目名称: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++语言实现)
// : 定义控制台应用程序的入口点。
#include
#include
#include
#define SEND_SIZE 32
#define PACKET_SIZE 4096
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#pragma comment(lib,"Ws2_")
struct icmp
{
unsigned char icmp_type;
//类型
unsigned char icmp_code;
//编码
unsigned short icmp_chksum;
//校验和
unsigned short icmp_id;
//标示符
unsigned short icmp_seq;
//顺序号
unsigned long icmp_data;
//数据
};
struct ip
{
unsigned char ip_hl:4;
//报头长度
unsigned char ip_v:4;
//版本号
unsigned char ip_tos;
//服务类型
unsigned short ip_len;
//总长度
unsigned short ip_id;
//标识
unsigned short ip_off;
//标志
unsigned char ip_ttl;
//生存时间
unsigned char ip_p;
//协议号
unsigned short ip_sum;
//报头校验和
unsigned long ip_src;
//源IP地址
unsigned long ip_dst;
//目的IP地址
};
char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
struct sockaddr_in dest_addr;
struct sockaddr_in from_addr;
int sockfd;
int pid;
unsigned short cal_chksum(unsigned short *addr,int len);
int pack(int pack_no);
int unpack(unsigned char *buf,int len);
void send_packet(void);
void recv_packet(void);
int main(int argc, CHAR* argv[])
{
struct hostent *host;
struct protoent *protocol;
int timeout=1000;
int SEND_COUNT=4;
int i;
char *par_host;
char m_Input[100];
printf("Input IP: ");
gets(m_Input);
par_host=m_Input;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) return;
if ( LOBYTE( on ) != 2 ||
HIBYTE( on ) != 2 ) {
WSACleanup( );
return;
}
if( (protocol=getprotobyname("icmp") )==NULL) //返回对应于给定协议名的包含名字和协议号
{
}
if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)
{
printf("socket errorn");
exit(1);
printf("getprotobyname errorn"); //的protoent结构指针
exit(1);
}
if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout))<0) //设置套接口的选项
fprintf(stderr,"failed to set recv timeout: %dn",WSAGetLastError());
if(setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout))<0)
fprintf(stderr,"failed to set send timeout: %dn",WSAGetLastError());
memset(&dest_addr,0,sizeof(dest_addr));
dest__family=AF_INET;
if(host=gethostbyname(par_host) ) // 返回对应于给定主机名的主机信息
{
memcpy( (char *)&dest__addr,host->h_addr,host->h_length);
//resolve address to hostname
if(host=gethostbyaddr(host->h_addr,4,PF_INET))
par_host=host->h_name;
}
else if( dest__addr.s_addr=inet_addr(par_host)==INADDR_NONE)
{
}
printf("Unkown host %sn",par_host);
exit(1);
pid=_getpid();
printf("Pinging %s [%s]: with %d bytes of
data:nn",par_host,inet_ntoa(dest__addr),SEND_SIZE);
for(i=0;i { } } //this algorithm is referenced from other's unsigned short cal_chksum(unsigned short *addr,int len) { int nleft=len; int sum=0; unsigned short *w=addr; unsigned short answer=0; while(nleft>1) { sum+=*w++; nleft-=2; } if( nleft==1) //处理ICMP报头为奇数个字节时累加最后一个 { *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return answer; } //打包 int pack(int pack_no) send_packet(); recv_packet(); Sleep(1000); { int packsize; struct icmp *icmp; packsize=8+SEND_SIZE; icmp=(struct icmp*)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( (unsigned short *)icmp,packsize); /*校验算法*/ return packsize; } //解包 int unpack(char *buf,int len) { struct ip *ip; struct icmp *icmp; double rtt; int iphdrlen; ip=(struct ip *)buf; iphdrlen=ip->ip_hl*4; icmp=(struct icmp *)(buf+iphdrlen); if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) ) { len=len-iphdrlen-8; rtt=GetTickCount()-icmp->icmp_data; printf("Reply from %s: bytes=%d time=%.0fms TTL=%d icmp_seq=%un", inet_ntoa(from__addr), len, rtt, ip->ip_ttl, icmp->icmp_seq); return 1; } return 0; } //发送 void send_packet() { int packetsize; static int pack_no=0; packetsize=pack(pack_no++); if( sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0 ) printf("Destination host unreachable.n"); // printf("send NO %dn",pack_no-1); } //接收 void recv_packet() { int n,fromlen; int success; fromlen=sizeof(from_addr); do { if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,(struct sockaddr *)&from_addr,&fromlen)) >=0) success=unpack(recvpacket,n); else if (WSAGetLastError() == WSAETIMEDOUT) { printf("Request timed out.n"); return; } }while(!success); } 七.结果分析 运行结果如图1所示: 图1 运行结果 运行结果可看出此程序不断地在向172.20.72.12发送数据包,并且得到了应答。 八.个人总结 本次课程设计较好地实现了要求做到的功能,但同时也遇到不少的困难和挑战。通过本次实验我们了解到 ICMP协议是一个非常重要的协议,它对于网络安全、网络的正常运作具有极其重要的意义,它被用于在IP主机、路由器之间传递控制消息,如网络通不通、主机是否可达、路由是否可用等。实验中将原始数据在网络层添加IP报头和数据链路层添加ICMP的报头,再在目的端解封装这两个报头。通过这次实验,我们不但加深了对Socket的原始套接字RAW编程的理解,同时也对IP和ICMP协议有了进一步的认识。 教 师 评 语 教师签字: 年 月 日
版权声明:本文标题:ping实验报告 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1703202473a43897.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论