您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > Ping程序设计(c语言课程设计)
07网络工程本制作人:北-624寝室负责人:赖文斌第四篇网络编程第九章ping程序设计ping命令是使用频率极高的一个网络测试命令,用以测试从一个主机到另一个主机间的网络上否可达。windows自带的ping命令具有强大的功能,它有很多选项用于实现不同的测试目的。本章模仿windows的ping命令,用c语言实现了一个简单的命令。本章着重讲述ping命令的实现原理和c语言的网络编程方法。读者可以在本章的基础上,对本章实现的ping命令进行扩展,开发出功能更强大、更完善的ping命令,并进一步掌握网络编程的方法。9.1设计目的本章通过设计Ping程序,讲解Ping程序的实现原理,并初步讲解了c语言网络编程技术。本章涉及很多网络编程函数和编程技巧。包括库文件的导入;winsock的初始化、注销;socket的创建、关闭;设置socket选项;根据主机名获取IP地址;从堆中分配一定数量的空间、释放从堆中分配的空间;获取当前进程ID号;数据报的发送;数据报的接等。通过本程序的训练,使读者对网络编程有一定的了解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。9.2功能描述本章用c语言实现的ping命令,能用于测试一个主机到另一个主机间的联通情况,程序还提供了几个选项以实现不同的功能。(1)实现ping功能。程序能实现基本的ping操作,发送ICMP回显请求报文,接收显应答报文。(2)能记录路由。程序提供了“-r”选项,用以记录从源主机到目的主机的路由。(3)能输出指定条数的记录。程序提供了“-n”选项,用以输出指定条数的记录。(4)能按照指定大小输出每条记录。程序提供了“datasize”选项,用以指定输出的数据报的大小。(5)能输出用户帮助。程序提供了用户帮助,显示程序提供的选项以及选项格式等。9.3总体设计9.3.1功能模块设计1.功能模块图本系统共有4个模块,分别是初始化模块、功能控制模块、数据控制模块、数据报解读模块和ping测试模块,如图9.1所示。各模块功能描述如下。图9.1系统模块图(1)初始化模块。改模块用于初始化各个全局变量,为全局变量赋初始值;初始化,加载库。(2)功能控制模块。改模块是被其它模块调用,其功能包括获取参数、计算校验和填充数据报文、释放占用资源和显示用户帮助。(3)数据报解读模块。改模块用于解读接收到的报文和选项。(4)测试模块。改模块是本程序的核心模块,调用其他模块实现其功能,主要是实现的功能。2.系统流程图系统执行的流程图9.2所示。程序首先调用IniPing()函数初始化各全局变量,然后GetArgments()函数获取用户输入的参数,检查用户输入的参数,如果参数不正确或者没有输入参数,则显示用户帮助信息(Userhelp),并结束程序;如果参数正确,则对指定目的地执行Ping命令,如果Ping通,则显示Ping结果并释放占用资源,如果没有Ping通,则报告错误信息,并释放占用资源。Ping程序设计初始化模块数据报解读模块功能控制模块Ping测试模块图9.2系统流程图3.参数获取(GetArgments()函数)流程图获取的参数包括“-r”(记录路由)、“-n”(记录条数程序,任意的整数)和datasize(数据报大小)。程序首先判断每一个参数的第一字符,如果第一个字符是“-”(短横线),则认为是“-r”或者“-n”中的一个,然后作进一步判断。如果该参数的第二个字符是数字,则判断该参数为记录的条数,如果该参数的第二个字符是“r”,则判断该参数为“-r”,用于开始初始化个变量获取参数信息输入参数是否正确?Ping目的地Ping成功?输出Ping结果释放占用资源结束输出错误信息显示帮助信息记录路由;如果参数的第一个字符是数字,则认为参数是IP地址;或者datasize,然后作进一步的判断。如果该参数中不存在非数字的字符,则判断该参数为datasize;如果存在非数字的字符,则判断该参数为IP地址;其他情况则判断为主机名。参数获取的流程如图9.3所示。图9.3参数获取流程图开始Argc==1?检查第一i个参数的第一个字符是“-”?检查第一i个参数的第二个字符是数字?该参数表示要获取的记录数转换成十进制记录到全局变量packetNUM还有参数?结束是数字?该参数中有非数字字符?该参数表示IP地址该参数表示数据报大小该参数表示主机名是“r”?显示用户帮助设标志位RecordFlag为tureI=i+1记录到变量Lpdest中记录到变量Datasize中记录到变量Lpdest中4.ping()函数流程图ping()函数是本程序的核心部分它调用其他模块的函数来实现,其主要步骤包括创建接字,设置路由选项(如果需要的话)、设置接收和发送超时值、名字解析(如果需要的话)、分配内存、创建ICMP报文、发送ICMP请求报文、接收ICMP应答报文和解读ICMP报文。其执行流程如图9.4所示。开始创建原始套接字创建成功?记录路由?设置接收和发送超时值为每个ICMP设置路由选项设置成功?名字解析?根据主机名获取各种参数获取成功?设置目的地址各项字段根据ICMP报文大小分配内存分配成功创建ICMP报文发送ICMP请求发送成功?超时发送?输出超时发送接收ICMP应答输出失败信息图9.4Ping函数流程图9.3.2数据结构设计本程序定义了3个结构体:-iphdr、-icmphdr、和-ipotionhdr,分别用于存放IP报头信息、ICMP报头信息和IP路由选项信息。1.定义IP报头结构体Typedefstruct_iphdr{Unsignedinth_len:4;Unsignedintversion:4;Unsignedchartos;Unsignedshorttotal_len;Unsignedshortident;Unsignedshortfrag_flags;Unsignedcharttl;Unsignedchorproto;Unsignedshortchecksum;UnsignedintsourceIP;UnsignedintdestIP;}IpHeader;接收成功?超时接收?输出失败信息输出超时接收读取ICMP数据报文记录数达到指定值?其中各字段表示意义如下。h-len:4:表示IP报头长度,首部长度指的是首部占32bit字的数目,包括任何选项。由于它是一个4bit字段,因此首部最长为60个字节,不包括任何选项的IP报头是20个字节。Version:4:表示IP的版本号,这里表示Ipv4.。Top:表示服务的类型,可以表示最小时延,最大吞吐量,最高可靠性和最小费用。Total–len:整个IP数据报的总长度。Ident:唯一的标识符,标识主机发送的每一份数据报。Frag-flags:分段标志,表示过长的数据报是否要分段。Ttl:生存期,表示数据报可以经过的最多路由器数。Proto:协议类型(TCP、UDP等)。Checksum:校验和。sourceIP:源IP地址。destIP:目的IP地址。2.定义ICMP报头结构体Typedefstruct–icmphdr{BYTEi_type;BYTEi_code:USHORTi_cksum;USHORTi_id;USHORTi_seq;ULONGtimestamp;}IcmpHeader;其中各字段表示意义如下。I_tye:ICMP报文类型。I_code:该类型中的代码号,一种ICMP报文的类型号和该类型中的代码号共同决定。、I_cksum:校验和。I_seq:序列号,序列号从0开始,每发送一次新的回显请求就加1.Timestamp:时间。3.定义IP选项结构体Typedefstruct_ipoptionhdr{Unsignedcharcode;Unsignedcharlen;Unsignedcharptr;Unsignedloangaddr[9];}IcmpHeader;其中各字段表示意义如下。Code:指明IP选项类型,对于路由记录选项,它的值是7。Len:选项头长度。Ptr:地址指针字段,是一个基于1的指针,指向存放下一个IP地址的位置。addr[9]:记录的Ip地址列表,由于IP首部中选项的空间有限,所以可以记录的Ip地址最多是9个。9.33函数功能描述1)IntPing()函数原型:voidIntPing()IntPing()函数用于初始化ping所需的全局变量,为各个变量赋初始值。2)userHelp()函数原型:voiduserHelp()userHelp()函数用于显示用户帮助信息。当程序检查到参数错误或者没有必要的参数(如主机IP地址或者主机名)时,则会调用此函数显示帮助信息。3)GetArgments()函数原型:voidGetArgments(intargc,char**argv)GetArgments()函数用于获取用户提交的参数。其中argc表示获取的参数个数,argv用于存储获取的参数,这两个形参和主函数中的形参表示的意义一样的。4)checkSum()函数原型:USHORTcheckSum(USHORT*buffer,intsize)checkSum()函数用于计算校验和。计算过程是首先把数据报头中的校验和字段设置为0,然后对首部中每个16bit进行二字段进制反码求和(整个首部看成是由一串16bit的字组成),结果存在校验和字段中。其中buffer用于存放ICMP数据,size表示ICMP报文大小。5)FillCMPData()函数原型:voidFillCMPData()FillCMPData()函数用于填充ICMP数据报中各个字段。其中icmp_data表示ICMP数据,datasize表示ICMP报文大小。6)reeRes()函数原型:voidreeRes()reeRes()函数用于释放占用的资源,包括关闭初始化socket调用的函数的、关闭创建的socket和释放分配的内存等。7)DecodeIPOptions()函数原型:voidDecodeIPOptions()DecodeIPOptions()函数用于解读IP选项,从中读出从源主机到目的主机经过的路由,并输出路由信息。Buf表示存放接收到的ICMP报文的缓冲区,bytes表示接收到的字节数。8)DecodelICMPHeader()函数原型:voidDecodelICMPHeader(char*buf,intbytes,SOCKADDR_IN*from)DecodelICMPHeader()函数用于解读ICMP报文信息。Buf表示存放接收到的ICMP报文的缓冲区,bytes表示接收到的字节数,from表示发送ICMP回显应答的主机IP地址。9)PingTest()函数原型:voidPingTest(inttimeout)PingTest()函数用于进行Ping操作。其中timeout表示设定的发送超时值。9.4程序实现9.1.4源码分析1.程序预处理/*导入库文件*/#pragmacomment(lib,ws2_32.lib)/*加载头文件*/#includewinsock2.h#includews2tcpip.h#includestdio.h#includestdlib.h#includemath.h/*定义常量*//*表示要记录路由*/#defineIP_RECORD_ROUTE0x7/*默认数据报大小*/#defineDEF_PACKET_SIZE32/*最大的ICMP数据报大小*/#defineMAX_PACKET1024/*最大IP头长度*/#defineMAX_IP_HDR_SIZE60/*ICMP报文类型,回显请求*/#defineICMP_ECHO8/*ICMP报文类型,回显应答*/#defineICMP_ECHOREPLY0/*最小的ICMP数据报大小*/#defineICMP_MIN8/*自定义函数原型*/voidInitPing();voidUserHelp();voidGetArgment
本文标题:Ping程序设计(c语言课程设计)
链接地址:https://www.777doc.com/doc-3736403 .html