




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、ing命令的设计与实现ping命令的设计与实现21/21ping命令的设计与实现设计报告课程设计名称专业班级计算机网络ping命令的设计与实现计科094同组人姓名同组人学号实验日期2013-04-10指导教师成绩2013年04月10日设计目的和要求1、实验目的:Ping命令向目的主机发送ICMPECHOREQUEST恳求并接收目的主机返回的响应报文,用来查验当地主机和远程的主机能否连结。2.实验要求:利用ICMP数据包,测试主机的连通性,经过课程设计,使学生熟习ICMP报文构造,使学生对ICMP有更深的理解。要求:输出参照系统自带ping程序,命令行运转:pingip二、设计说明设计剖析:使用
2、原始套接字能够读写ICMP分组,利用原始套接字发送ICMP回显恳求,并接收ICMP回显应答,经过icmp_send()发送ICMP回显示恳求包,icmp_recv()接收ping目的主机的答复,并使用终端信号办理函数SIGINT办理信号,成立两个线程,一个用于发送数据,另一个用于接收响应数据,主程序等候两个线程运转完成后再进行下一步动作。最后,主程序讲发送数据和接收的数据进行统计,并将结果打印出来。系统运转环境:虚构机:Fedora14(linux操作系统)gcc设计中的要点和难点:ICMP数据包的打包和解包,以及从CRC16校验算法的剖析实现输入和输出条件:在linux系统下运转ping在出
3、现4个响应包后按Ctrl+c键停止发送。三、系统详尽设计Ping命令的设计与实现Ping命令向目的主机发送ICMPECHOREQUEST恳求并接收目的主机返回的响应报文,用来查验当地主机和远程的主机能否连结。协议格式图1.1中已经对协议的报文格式进行了说明。代码值为0,表示ICMP的回显恳求。种类为0,代码为为16为的crc16的算法。Ping的客户端方式的种类为8,0是,是ICMP回显应答。查验和078151631种类(8位)代码(8位)校验和(16位)此部分不一样的种类和代码格式不一样图1.1ICMP报文的数据格式图1.2所示为ping所使用的种类和代码格式。包含16位的标始符和16为的序
4、列号。序列号是用于表记发送或许响应的序号,而标示符往常用于表示发送和接收此报的用户,一眼用进度的PID来辨别。078151631种类代码(0)校验和8或0)标示符序列符占位字节图1.2ping的数据格式比如一个用户的进度PID为1000,发送了一个序列号为1的回显恳求报文,当此报文被目的主机正确办理并返回后,能够用PID来辨别能否为目前的用户,而且用序列号来辨别哪个报文被返回,经过发送报文到目的主机并接受响应,能够计算发送和接收两者之间的时间差,来判断网络的情况。如图1.3所示,ping程序一般依据图中的框架进行设计。主要分为发送数据和接收数据及计算时间差。发送数据对组织好的数据进行发送,接收
5、数据从网络上接收数据并判断其合法性,比如判断能否本进度发出的报文等。开始设置发送数据接收数据计算机发送数据校解包判断正误发送数据计算时速差结束图1.3ping程序的基本框架因为ICMP并进行校验。一定使用原始套接字进行设计,要手动设置IP的头部和ICMP的头部校验和函数TCP/IP协议栈使用的校验算法是比较经典的,回计算结果。需要注意的是对奇数个字节数据的计算,的字节,低字节填补了0。对16为的数据进行累加计算,并返是将最后的有效数据作为最高位/*CRC16校验和计算icmp_cksum参数:data:数据len:数据长度返回值:计算结果,short种类*/staticunsignedshor
6、ticmp_cksum(unsignedchar*data,intlen)intsum=0;/*计算结果*/intodd=len&0 x01;/*能否为奇数*/unsignedshort*value=(unsignedshort*)data;/*将数据依据2字节为单位累加起来*/while(len&0 xfffe)sum+=*(unsignedshort*)data;data+=2;len-=2;/*判断能否为奇数个数据,若ICMP报头为奇数个字节,会剩下最后一字节。*/if(odd)unsignedshorttmp=(*data)16)+(sum&0 xffff);sum+=(sum16);
7、returnsum;设置IP发送报文的头部ip头部格式:structip#if_BYTE_ORDER=_LITTLE_ENDIAN/*假如为小端*/gnedintip_v:4;/*版本*/#endif#if_BYTE_ORDER=_BIG_ENDIAN/*假如为大端*/unsignedintip_v:4;/*版本*/unsignedintip_hl:4;/*头部长度*/#endifu_int8_tip_tos;/*TOS,服务种类*/u_shortip_len;/*总长度*/u_shortip_id;/*表记值*/u_shortip_off;*段偏移值*/u_int8_tip_ttl;/*TT
8、L,生计时间*/u_int8_tip_p;/*协议种类*/u_shortip_sum;/*校验和*/structin_addrip_src,ip_dst;/*源地点和目的地点*/;设置ICMP发送报文的头部关于回显恳求的ICMP报文,下边是ICMP构造简化形式:structicmpu_int8_ticmp_type;/*信息种类*/u_int8_ticmp_code;/*信息种类的子码*/u_int16_ticmp_cksum;/*校验和*/unionu_charih_pptr;/*ICMP_PARAMPROB*/structin_addrih_gwaddr;/*网关地点*/structih_
9、idseq/*显示数据报*/u_int16_ticd_id;/*数据报u_int16_ticd_seq;/*数据报的序号ih_idseq;icmp_hun;ID*/*/#define#defineicmp_idicmp_sequnionstructu_int8_tid_data1;/*数据*/icmp_dun;#defineicmp_dataicmp_dun.id_data;即仅包含信息种类、信息代码、校验和、数据报的ID、数据报的序列号即段几个部分。校验和的值在计算以前其余的值应当先进行填补,而校验和也需要设置为来占位,而后在计算真实的校验和值。ICMP数据0ICMP回显得数据部分能够随意设
10、置,可是以太网包的总长度不可以小于以太网的最小值,即总长度不可以小于46,因为IP头部为20字节,ICMP头部为8个字节,以太网头部占用14个字节,所以ICMP回显包的最小值为46-20-8-14=4个字节。ICMP回显恳求的种类为8,即ICMP-ECHO。ICMP回显恳求的代码值为0.ICMP回显恳求的序列号是一个16位的值,往常由一个递加的值生成。?进行ICMPICMP回显恳求的ID用于差别,往常用进度的PID填补。头部校验的代码以下:/*设置ICMP报头*/staticvoidicmp_pack(structicmp*icmph,intseq,structtimeval*tv,intle
11、ngth)unsignedchari=0;/*设置报头*/icmph-icmp_type=ICMP_ECHO;icmph-icmp_code=0;icmph-icmp_cksum=0;/*ICMP/*code值为/*先将回显恳求*/0*/cksum值填写0,便于以后的cksum计算*/icmph-icmp_seq=seq;icmph-icmp_id=pid&0 xffff;/*本报的序列号*/*填写PID*/for(i=0;iicmp_datai=i;/*计算校验和*/icmph-icmp_cksum=icmp_cksum(unsignedchar*)icmph,length);剥离ICMP接
12、受报文的头部函数icmp_unpack()用于剥离IP头部,剖析ICMP头部的值。判断能否为正确的报文,并打印结果。参数buf为剥去了以太网部分数据的IP数据报文,len为数据长度。能够利用的参数迅速地跳ICMP报文部分,IP构造的ip_hl表记IP头部的长度,因为ip_hl4字节单位,所以需要乘以4来获取ICMP段的地点。ICMPIP头部表记的是获取ICMP数据段后,判断其种类能否为ICMP_ECHOREPLY,并核实其表记能否为本进度的PID。因为需要判断数据报文的来回时间,在本程序中需要先查找这个包发送时的时间,与目前时间进行计算后,能够得出当地主机与目标主机之间网络ICMP回显报文的差
13、值。程序需要累加成功接收到的报文用于程序退出时的统计。/*解压接收到的包,并打印信息*/staticinticmp_unpack(char*buf,intlen)inti,iphdrlen;structip*ip=NULL;structicmp*icmp=NULL;intrtt;ip=(structip*)buf;iphdrlen=ip-ip_hl*4;icmp=(structicmp*)(buf+iphdrlen);len-=iphdrlen;if(lenicmp_type=ICMP_ECHOREPLY)&(icmp-icmp_id=pid)structtimevaltv_internel,
14、tv_recv,tv_send;/*在发送表格中查找已经发送的包,依据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=tv_internel.tv_sec*1000+tv_internel.tv_u
15、sec/1000;/*打印结果,包含*ICMP段长度源IP地点包的序列号TTL时间差*/*/printf(%dbytefrom%s:icmp_seq=%uttl=%drtt=%dmsn,len,inet_ntoa(ip-ip_src),icmp-icmp_seq,ip-ip_ttl,rtt);packet_recv+;/*接收包数目加1*/elsereturn-1;函数的返回值为-1时表示褚翠,其余值则正常。计算时间差因为需要评估网络情况,在发送数据报文的时候保留发送时间,接收到报文后,计算两个时刻之间的差值,生成了ICMP源主机和目标主机之间的网络情况的时间评估。/*计算时间差time_su
16、b参数:end,接收到的时间begin,开始发送的时间返回值:使用的时间*/staticstructtimevalicmp_tvsub(structtimevalend,structtimevalbegin)structtimevaltv;/*计算差值*/tv.tv_sec=end.tv_sec-begin.tv_sec;tv.tv_usec=end.tv_usec-begin.tv_usec;/*假如接收时间的usec值小于发送时的usec值,从usec域借位*/if(tv.tv_usec0)tv.tv_sec-;tv.tv_usec+=1000000;returntv;发送报文发送报文函数
17、是一个线程,每隔1s向目的主机发送一个ICMP回显恳求报文,它在整个程序处于激活状态(alive为1)是向来发送报文。1)获取目前的时间值,依据序列号packet_send将ICMP报文打包到缓冲区send_buff中后,发送到目的地点。发送成功后,记录发送报文的状态:序号seq为packet_send。标记flag为1,表示已经发送可是没有收到响应。发送时间为以前获取的时间。2)每次发送成功后序号值会增添1,即packet_send+.3)在线程开始进入主循环while(alive)以前,将整个程序的开始发送时间记录下来,用于在程序退出的时候进行全局统计,即gettimeofday(&tv_
18、begin,NULL),j将时间保留在变量tv_begin中。/*发送ICMP回显恳求包*/staticvoid*icmp_send(void*argv)structtimevaltv;tv.tv_usec=0;tv.tv_sec=1;gettimeofday(&tv_begin,NULL);/*保留程序开始发送数据的时间*/while(alive)intsize=0;structtimevaltv;gettimeofday(&tv,NULL);/*目前包的发送时间*/icmp_pack(structicmp*)send_buff,packet_send,&tv,64);/*打包数据*/siz
19、e=sendto(rawsock,send_buff,64,0,(structsockaddr*)&dest,sizeof(dest);/*将数据由指定的socket发送给目的地点*/if(sizeseq=packet_send;/*设置seq*/packet-flag=1;/*已经使用*/gettimeofday(&packet-tv_begin,NULL);/*发送时间*/packet_send+;/*计数增添*/sleep(1);/*每隔一秒,发送一个ICMP回显恳求包*/接收报文与发送函数同样,接收报文也用一个线程实现,使用select()轮询等候报文到来。当接收到一个报文后使用函数i
20、cmp_unpack()来解包和查找报文以前发送时的记录,获取发送时间,计算收发差值并打印信息。(1)接收成功后将合法的报文记录重置为没有使用,flag为0.。2)接收报文数目增添1.3)为了防备丢包,select()轮询时间设置的比较短。/*接收ping目的主机的答复*/staticvoid*icmp_recv(void*argv)/*轮训等候时间*/structtimevaltv;tv.tv_usec=200;tv.tv_sec=0;fd_setreadfd;/*当没有信号发出向来接收数据*/while(alive)intret=0;FD_ZERO(&readfd);FD_SET(raws
21、ock,&readfd);ret=select(rawsock+1,&readfd,NULL,NULL,&tv);switch(ret)case-1:/*break;case0:break;/*default:/*错误发生超时*/收到一个包*/*/intfromlen=0;structsockaddrfrom;/*接收数据*/intsize=recv(rawsock,recv_buff,sizeof(recv_buff),0);if(errno=EINTR)perror(recvfromerror);continue;ret=icmp_unpack(recv_buff,size);/*解包并设
22、置有关变量*/if(ret=-1)continue;break;主函数过程Ping程序的实现使用了两个线程,一个线程icmp_recv()用于接收远程主机的响应。当变量1.ping数据的数据构造aliveicmp_send()用于发送恳求,一个线程为0时,两个线程退出。种类为构造structpingm_packet的变量pingpacket用于保留发送数据报文的状态:tv_begin用于保留发送的时间。tv_end用于保留数据报文接收到的时间。seq是序列号,用于表记报文,作为索引。flag用于表示本单元的状态,1表示数据报文已经发送,可是没有收到回应包;0表示已经接收到回应报文,这个单元能够
23、再次用于表记发送的报文。/*保留已经发送包的状态值*/typedefstructpingm_pakcetstructtimevaltv_begin;structtimevaltv_end;/*发送的时间*/*接收到的时间*/shortseq;intflag;/*序列号*/*1,表示已经发送但没有接收到回应包0,表示接收到回应包*/pingm_pakcet;staticpingm_pakcetpingpacket128;SIGINT办理函数本程序借去了信号SIGINT,用函数icmp_sigint()对SIGINT进行办理。当用户按下Ctrl+C键时,将alive设置为0,使得接收和发送两个线程
24、退出,并计算结束时的时间。代码以下:/*终端信号办理函数SIGINT*/staticvoidicmp_sigint(intsigno)/*告诉接收和发送线程结束程序*/alive=0;/*读取程序结束时间*/gettimeofday(&tv_end,NULL);/*计算一下总合所用时间*/tv_interval=icmp_tvsub(tv_end,tv_begin);return;3.查找数组中的标示函数icmp_findpacket()函数icmp_findpacket()用于在数组pingpacket中查找一个报文的表记,参数为-1时表示查找一个空包,寄存已经发送成功的数据报文;其余值表示
25、查找seq般配的表记。/*查找一个适合的包地点当seq为-1时,表示查找空包其余值表示查找seq对应的包*/staticpingm_pakcet*icmp_findpacket(intseq)inti=0;pingm_pakcet*found=NULL;/*查找包的地点*/if(seq=-1)/*查找空的地点*/for(i=0;i=0)/*查找对应SEQ的包*/for(i=0;i128;i+)if(pingpacketi.seq=seq)found=&pingpacketi;break;returnfound;4.统计数据结果函数icmp_statistics()icmp_statistics
26、()函数用于统计整体的结果,包含成功发送的报文数目、成功接收的报文数目、丢掉报文的百分比和总合程序运转的时间。/*打印所有ICMP发送接收统计结果*/staticvoidicmp_statistics(void)longtime=(tv_interval.tv_sec*1000)+(tv_interval.tv_usec/1000);printf(%spingstatisticsn,dest_str);/*目的邋IP地点*/printf(%dpacketstransmitted,%dreceived,%d%cpacketloss,time%dmsn,packet_send,/*发送*/pack
27、et_recv,/*接收*/(packet_send-packet_recv)*100/packet_send,/*丢掉百分比*/%,time);/*时间*/主函数main()在程序中需要注意以下几点:使用getprotobyname()函数获取icmp对应的ICMP协议值。对输入的目的主机地点兼容域名和IP地点,使用gethostbyname()函数获取DNS对应的IP地点,inet_addr()函数获取字符串种类的IP地点对应的整型值。为了防备远程主机发送过大的包或许当地来不及接收现象的发生,setsockopt(rawsock,、SOL_SOCKET、SO_RCVBUF、&size、si
28、zeof(size)函数将socket的接收缓冲区设置为128KB。对信号SIGINT进行了截取。成立两个线程icmp_send()和icmp_recv()进行接收和发送,而后主程序等候两个线程结束。主函数初始化一些一定的头文件、函数的申明及全局变量的申明放在这里。#include#include#include#include#include#include#include#include#include#include#include/*bzero*/#include#includestaticpingm_pakcet*icmp_findpacket(intseq);staticunsig
29、nedshorticmp_cksum(unsignedchar*data,intlen);staticstructtimevalicmp_tvsub(structtimevalend,structtimevalbegin);staticvoidicmp_statistics(void);staticvoidicmp_pack(structicmp*icmph,intseq,structtimeval*tv,intlength);staticinticmp_unpack(char*buf,intlen);staticvoid*icmp_recv(void*argv);staticvoid*icm
30、p_send(void*argv);staticvoidicmp_sigint(intsigno);staticvoidicmp_usage();/*保留已经发送包的状态值*/typedefstructpingm_pakcetstructtimevaltv_begin;structtimevaltv_end;/*发送的时间*/*接收到的时间*/shortseq;intflag;/*序列号*/*1,表示已经发送但没有接收到回应包0,表示接收到回应包*/pingm_pakcet;staticpingm_pakcetpingpacket128;#defineK1024#defineBUFFERSIZ
31、E72/*发送缓冲区大小*/staticunsignedcharsend_buffBUFFERSIZE;staticunsignedcharrecv_buff2*K;/*为防备接收溢出,接收缓冲区设置大一些*/staticstructsockaddr_indest;/*目的地点*/staticintrawsock=0;/*发送和接收线程需要的socket描绘符*/staticpid_tpid=0;/*进度PID*/staticintalive=0;/*能否接收到退出信号*/staticshortpacket_send=0;/*已经发送的数据包多少*/staticshortpacket_recv
32、=0;/*已经接收的数据包多少*/staticchardest_str80;/*目的主机字符串*/staticstructtimevaltv_begin,tv_end,tv_interval;/*本程序开始发送、结束和时间间隔*/staticvoidicmp_usage()/*ping加IP地点或许域名*/printf(pingaaa.bbb.ccc.dddn);进行数据报文发送以前的准备工作主要包含获取目的主机的IP地点、建立原始套接字、初始化缓冲区和变量等工作、这些工作里面还包含接收缓冲区的改正,防备返回数据过大造成数据缓冲区溢出。在本段代码里使用了getprotobyname()函数来获
33、取ICMP协议的种类,而不用用户记忆协议的详细种类,只需记着名称就能够了。/*主程序*/intmain(intargc,char*argv)structhostent*host=NULL;/*hostent的定义以下:structhostentchar*h_name;char*h_aliases;inth_addrtype;inth_length;char*h_addr_list;地点的正式名称。空字节-地点的预备名称的指针。地点种类;往常是AF_INET。地点的比专长度。零字节-主机网络地点指针。网络字节顺序#defineh_addrh_addr_list0h_addr_list中的第一地点
34、。;*/structprotoent*protocol=NULL;/*获得协议编号0到structprotoentchar*char*short*4的协议数据p_name;/名称p_aliases;/又名p_proto;/编号*/charprotoname=icmp;unsignedlonginaddr=1;intsize=128*K;/*参数能否数目正确*/if(argcp_proto);if(rawsock0)perror(socket);return-1;/*为了与其余进度的ping程序差别,加入pid*/pid=getuid();/*增大接收缓冲区,防备接收的包被覆盖*/setsock
35、opt(rawsock,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size);/*原型:externvoidbzero(void*s,intn);用法:#include功能:置字节字符串s的前n个字节为零且包含0*/bzero(&dest,sizeof(dest);/*获取目的地点的IP地点*/dest.sin_family=AF_INET;/*输入的目的地点为字符串IP地点*/inaddr=inet_addr(argv1);if(inaddr=INADDR_NONE)/*为DNS地点*/host=gethostbyname(argv1);if(host=NULL)p
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中班防走丢课件
- 各科全面复习2024年国际物流师试题与答案
- 2024年CPMM独立学习的试题及答案
- 南京市五校联盟2024-2025学年高二上学期期末考试 化学试卷(含答案详解)
- 成为CPSM考试专家的路径试题及答案
- 保健调理知识培训课件
- CPSM考试系统复习试题及答案
- 保险防忽悠课件
- 生态平衡的重要性:试题及答案
- 结构化学习国际物流师试题及答案
- 【电力服务收费项目及标准】 电力维护收费标准
- 软件工程导论(第六版)电子教案(第1-13章)
- 卵巢癌诊治指南
- 【超星尔雅学习通】《海洋与人类文明(浙江海洋大学)》章节测试题及答案
- 河南省高中毕业生登记表【范本模板】
- TSIOT 315-2021 智慧健康养老 老年人跌倒智能监测系统技术要求
- JJG 52-2013弹性元件式一般压力表、压力真空表和真空表
- GB/T 6289-2013夹扭钳和剪切钳术语
- 不参与电信网络诈骗承诺书
- GA/T 718-2007枪支致伤力的法庭科学鉴定判据
- 配气机构的设计
评论
0/150
提交评论