文档介绍:该【ping命令设计与实现 】是由【泰山小桥流水】上传分享,文档一共【21】页,该文档可以免费在线阅读,需要了解更多关于【ping命令设计与实现 】的内容,可以使用淘豆网的站内搜索功能,选择自己适合的文档,以下文字是截取该文章内的部分文字,如需要获得完整电子版,请下载此文档到您的设备,方便您编辑和打印。精选文档
精选文档
1
精选文档
设计报告
课程
设计名称
专业班级
计算机网络
《ping命令的设计与实现》
计科094
精选文档
精选文档
21
精选文档
同组人姓名
同组人学号
精选文档
精选文档
21
精选文档
实验日期
2013-04-10
指导教师
成
绩
2013年04月10日
精选文档
精选文档
21
精选文档
设计目的和要求
1、实验目的:
Ping命令向目的主机发送ICMPECHO—REQUEST恳求并接收目的主机返回的响应报文,用来检验当地主机和远程的主机能否连结。
:
利用ICMP数据包,测试主机的连通性,经过课程设计,使学生熟****ICMP报文构造,使学生对ICMP有更深的理解。要求:输出参照系统自带ping程序,命令行运转:pingip
二、设计说明
设计分析:
使用原始套接字能够读写ICMP分组,利用原始套接字发送ICMP回显恳求,并接收ICMP
回显应答,经过icmp_send()发送ICMP回显示恳求包,icmp_recv()接收ping目的主
机的答复,并使用终端信号办理函数SIGINT办理信号,建立两个线程,一个用于发送数据,
另一个用于接收响应数据,主程序等候两个线程运转完成后再进行下一步动作。最后,主程
序讲发送数据和接收的数据进行统计,并将结果打印出来。
系统运转环境:
虚假机:Fedora14(linux操作系统)gcc
设计中的要点和难点:
ICMP数据包的打包和解包,以及从CRC16校验算法的分析实现
输入和输出条件:
在linux系统下运转ping在出现4个响应包后按Ctrl+c键停止发送。
精选文档
精选文档
5
精选文档
三、系统详尽设计
精选文档
精选文档
21
精选文档
《Ping命令的设计与实现》
Ping命令向目的主机发送ICMPECHO—REQUEST恳求并接收目的主机返回的响应报文,用来检验当地主机和远程的主机能否连结。
协议格式
精选文档
精选文档
7
精选文档
。
代码值为0,表示ICMP的回显恳求。种类为0,代码为
为16为的crc16的算法。
Ping的客户端方式的种类为8,
0是,是ICMP回显应答。检验和
精选文档
精选文档
21
精选文档
0
7
8
15
16
31
种类(8位)
代码(8
位)
校验和(16位)
此部分不一样的种类和代码格式不一样
。包含16位的标始符和16为的序列号。序列号是用于表记发送或许响应的序号,而标示符平常用于表示发送和接收此报的用户,一眼用进度的PID来鉴识。
078151631
种类
代码(0)校验和
8或0)
标示符序列符
占位字节
比方一个用户的进度PID为1000,发送了一个序列号为1的回显恳求报文,当此报文被目的主机正确办理并返回后,能够用PID来鉴识能否为目前的用户,而且用序列号来鉴识哪个报文被返回,经过发送报文到目的主机并接受响应,能够计算发送和接收两者之间的时间差,来判断网络的情况。
精选文档
精选文档
21
精选文档
,ping程序一般依照图中的框架进行设计。主要分为发送数据和接收数据及计算时间差。发送数据对组织好的数据进行发送,接收数据从网络上接收数据并判断其合法性,比方判断能否本进度发出的报文等。
开始
精选文档
精选文档
10
精选文档
设置发送
数据
接收数据
精选文档
精选文档
21
精选文档
计算机发
送数据校
解包判断
正误
精选文档
精选文档
21
精选文档
发送数据
计算时速
差
精选文档
精选文档
21
精选文档
结束
精选文档
精选文档
21
精选文档
因为ICMP
并进行校验。
一定使用原始套接字进行设计,要手动设置
IP
的头部和
ICMP
的头部
精选文档
精选文档
21
精选文档
校验和函数
精选文档
精选文档
16
精选文档
TCP/IP协议栈使用的校验算法是比较经典的,回计算结果。需要注意的是对奇数个字节数据的计算,的字节,低字节填补了0。
对16为的数据进行累加计算,并返
是将最后的有效数据作为最高位
精选文档
精选文档
21
精选文档
/*CRC16校验和计算icmp_cksum
参数:
data:数据
len:数据长度
返回值:
计算结果,short种类
*/
staticunsignedshorticmp_cksum(unsignedchar*data,intlen)
{
intsum=0;/*计算结果*/
intodd=len&0x01;/*能否为奇数*/
unsignedshort*value=(unsignedshort*)data;
/*将数据依照2字节为单位累加起来*/
while(len&0xfffe){
sum+=*(unsignedshort*)data;
data+=2;
len-=2;
}
精选文档
精选文档
21
精选文档
/*判断能否为奇数个数据,若
ICMP
报头为奇数个字节,会剩下最后一字节。
*/
精选文档
精选文档
21
精选文档
if(odd){
精选文档
精选文档
21
精选文档
unsignedshorttmp=((*data)<<8)&0xff00;
sum+=tmp;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
return~sum;
}
精选文档
精选文档
21
精选文档
设置IP发送报文的头部
ip头部格式:
structip
{
#if__BYTE_ORDER==__LITTLE_ENDIAN
/*
假如为小端*/
gnedintip_v:4;
/*版本*/
#endif
#if__BYTE_ORDER==__BIG_ENDIAN
/*假如为大端*/
unsignedintip_v:4;
/*
版本*/
unsignedintip_hl:4;
/*
头部长度*/
#endif
u_int8_tip_tos;
/*TOS,服务种类
*/
u_shortip_len;
/*
总长度*/
u_shortip_id;
/*
表记值*/
u_shortip_off;
*
段偏移值*/
u_int8_tip_ttl;
/*TTL,生计时间
*/
u_int8_tip_p;
/*
协议种类*/
u_shortip_sum;
/*
校验和*/
structin_addrip_src,ip_dst;
/*
源地址和目的地址
*/
};
精选文档
精选文档
22
精选文档
设置ICMP发送报文的头部
关于回显恳求的ICMP报文,下边是ICMP构造简化形式:
structicmp
{
u_int8_ticmp_type;/*信息种类*/
u_int8_ticmp_code;/*信息种类的子码*/
u_int16_ticmp_cksum;/*校验和*/
union
{
u_charih_pptr;/*ICMP_PARAMPROB*/
structin_addrih_gwaddr;/*网关地址*/
structih_idseq/*显示数据报*/
{
精选文档
精选文档
23
精选文档
u_int16_ticd_id;/*数据报
u_int16_ticd_seq;/*数据报的序号
}ih_idseq;
}icmp_hun;
ID*/
*/
精选文档
精选文档
21
精选文档
#define
#define
icmp_id
icmp_seq
精选文档
精选文档
21
精选文档
union
{
struct
{
精选文档
精选文档
21
精选文档
u_int8_t
id_data[1];
/*
数据
*/
精选文档
精选文档
21
精选文档
}icmp_dun;
精选文档
精选文档
21
精选文档
#defineicmp_data
精选文档
精选文档
21
精选文档
};
精选文档
精选文档
21
精选文档
即仅包含信息种类、信息代码、校验和、数据报的ID、数据报的序列号即
段几个部分。校验和的值在计算从前其余的值应该先进行填补,而校验和也需要设置为
来占位,而后在计算真实的校验和值。
ICMP
数据
0
精选文档
精选文档
21
精选文档
ICMP回显得数据部分能够随意设置,可是以太网包的总长度不可以小于以太网的最小
值,即总长度不可以小于46,因为IP头部为20字节,ICMP头部为8个字节,以太网头部占用14个字节,所以ICMP回显包的最小值为46-20-8-14=4个字节。
ICMP回显恳求的种类为8,即ICMP-ECHO。
ICMP回显恳求的代码值为0.
ICMP回显恳求的序列号是一个16位的值,平常由一个递加的值生成。
精选文档
精选文档
32
精选文档
?
进行
ICMPICMP
回显恳求的ID用于差别,平常用进度的PID填补。
头部校验的代码以下:
精选文档
精选文档
21
精选文档
/*设置ICMP报头*/
staticvoidicmp_pack(structicmp*icmph,intseq,structtimeval*tv,intlength)
{
unsignedchari=0;
精选文档
精选文档
21
精选文档
/*设置报头*/
icmph->icmp_type=ICMP_ECHO;
icmph->icmp_code=0;
icmph->icmp_cksum=0;
/*ICMP
/*code值为
/*先将
回显恳求*/
0*/
cksum值填写
0,便于以后的
cksum计
精选文档
精选文档
21
精选文档
算*/
精选文档
精选文档
21
精选文档
icmph->icmp_seq=seq;icmph->icmp_id=pid&0xffff;
/*本报的序列号*/
/*填写PID*/
精选文档
精选文档
21
精选文档
for(i=0;i<length;i++)
icmph->icmp_data[i]=i;
/*计算校验和*/
icmph->icmp_cksum=icmp_cksum((unsignedchar*)icmph,length);
}
剥离ICMP接受报文的头部
精选文档
精选文档
21
精选文档
函数icmp_unpack()用于剥离IP头部,分析ICMP头部的值。判断能否为正确的
报文,并打印结果。
参数buf为剥去了以太网部分数据的IP数据报文,len为数据长度。能够利用
的参数迅速地跳ICMP报文部分,IP构造的ip_hl表记IP头部的长度,因为ip_hl
4字节单位,所以需要乘以4来获取ICMP段的地址。
ICMP
IP头部
表记的是
精选文档
精选文档
21
精选文档
获取ICMP数据段后,判断其种类能否为ICMP_ECHOREPLY,并核实其表记能否为本进度的PID。因为需要判断数据报文的来回时间,在本程序中需要先查找这个包发送时的时间,
与目前时间进行计算后,能够得出当地主机与目标主机之间网络ICMP回显报文的差值。
程序需要累加成功接收到的报文用于程序退出时的统计。
精选文档
精选文档
21
精选文档
/*解压接收到的包,并打印信息*/
staticinticmp_unpack(char*buf,intlen)
{
精选文档
精选文档
41
精选文档
inti,iphdrlen;
structip*ip=NULL;
structicmp*icmp=NULL;
intrtt;
ip=(structip*)buf;
iphdrlen=ip->ip_hl*4;
icmp=(structicmp*)(buf+iphdrlen);
len-=iphdrlen;
if(len<8)/*判断长度能否为ICMP
{
/*IP头部*/
/*IP头部长度*/
/*ICMP段的地址
包*/
*/
精选文档
精选文档
21
精选文档
printf("ICMPpackets\'slengthislessthan8\n");
return-1;
}
/*ICMP种类为ICMP_ECHOREPLY而且为本进度的PID*/
if((icmp->icmp_type==ICMP_ECHOREPLY)&&(icmp->icmp_id==pid))
{
structtimevaltv_internel,tv_recv,tv_send;
精选文档
精选文档
21
精选文档
/*在发送表格中查找已经发送的包,依照seq*/
pingm_pakcet*packet=icmp_findpacket(icmp->icmp_seq);
if(packet==NULL)
return-1;
packet->flag=0;/*撤消标记*/
tv_send=packet->tv_begin;/*获取本包的发送时间*/
gettimeofday(&tv_recv,NULL);/*读取此不时间,计算时间差
tv_internel=icmp_tvsub(tv_recv,tv_send);
rtt=*1000+;
/*打印结果,包含
*ICMP段长度源IP地址包的序列号TTL时间差
*/
*/
精选文档
精选文档
21
精选文档
printf("%dbytefrom%s:icmp_seq=%uttl=%drtt=%dms\n",
len,
inet_ntoa(ip->ip_src),
icmp->icmp_seq,
ip->ip_ttl,
,rtt);
packet_recv++;/*接收包数目加1*/
}
else
return-1;
}
函数的返回值为-1时表示褚翠,其余值则正常。
精选文档
精选文档
21
精选文档
计算时间差
因为需要评估网络情况,在发送数据报文的时候保留发送时间,接收到报文后,计算两个时刻之间的差值,生成了ICMP源主机和目标主机之间的网络情况的时间评估。
/*计算时间差time_sub
参数:
end,接收到的时间
begin,开始发送的时间
返回值:
使用的时间
*/
staticstructtimevalicmp_tvsub(structtimevalend,structtimevalbegin)
{
structtimevaltv;
/*计算差值*/
=-;
=-;
/*假如接收时间的usec值小于发送时的usec值,从usec域借位*/if(<0)
{
--;
+=1000000;
}
returntv;
}
发送报文
发送报文函数是一个线程,每隔1s向目的主机发送一个ICMP回显恳求报文,它在整
个程序处于激活状态(alive为1)是向来发送报文。
1)获取目前的时间值,依照序列号packet_send将ICMP报文打包到缓冲区send_buff
中后,发送到目的地址。发送成功后,记录发送报文的状态:
序号seq为packet_send。
标记flag为1,表示已经发送可是没有收到响应。
发送时间为从前获取的时间。
2)每次发送成功后序号值会增添1,即packet_send++.
3)在线程开始进入主循环while(alive)从前,将整个程序的开始发送时间记录下来,
精选文档
精选文档
46
精选文档