计算机网络工程课程设计报告题目:Ping程序的实现学生姓名:学号:专业班级:计科专业10102班同组姓名:指导教师:设计时间:2013年下学期第16周指导老师意见:评定成绩:签名:日期:年月日1目录一、课程设计的目的和意义......................................................2二、课程设计的内容和要求......................................................21.内容:......................................................................................22.要求:......................................................................................2三、课程设计的相关技术..........................................................2四、课程设计过程......................................................................21.Ping主模块.............................................................................22.功能控制模块..........................................................................43.数据报解析模块......................................................................5五、课程设计小结......................................................................6六、参考文献..............................................................................7七、附录(程序清单)........................................................7八、心得体会............................................................................112一、课程设计的目的和意义利用ICMP数据包、C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间的连通情况。通过本程序的训练,使学生熟悉ICMP报文结构,使学生对ICMP有更深的理解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。二、课程设计的内容和要求1.内容:用C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间的连通情况。2.要求:1)独立完成程序的设计、编码和调试。2)系统利用C语言实现,程序调试环境为TurboC或VC;3)按照课程设计规范书写课程设计报告。4)采用VC环境进行调试运行。三、课程设计的相关技术由于Ping程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。为了实现直接对IP和ICMP包进行操作,实验中使用RAW模式的socket编程。首先定义IP数据报首部,在IP数据报的基础上定义ICMP数据报首部,并初始化一些全局变量。接着自定义填充ICMP数据报字段函数FillICMPData()、校验和函数checksum()、解读ICMP报首部函数DecodeICMPHeader()、释放资源函Cleanup()。最后主函数通过调用这些函数来实现Ping命令功能。IP头与ICMP头的设置分别参照RFC791及RFC792的标准,包含所有必要信息。主程序设置main()函数,主函数用库函数实现套接字编程用于数据包发送及接收,其中,数据包发送调用sendto(),数据包接收调用recvfrom(),由于发送数据包时可能会遇到阻塞或者目标主机不通,造成超时,因此需要在发送数据包后调用一个函数判断是否超时,此处调用库函数setsockopt()来实现超时判断;其次,校验和函数采用移位方法进行计算。套接字所需要的文件有头文件Winsocket2.h、库文件WS2_32.LIB、动态库W32_32.DLL。创建套接字的时候参数的以及在创建套接字之前必须首先使用WSAStartup函数。四、课程设计过程1.Ping主模块Ping()函数是本程序的核心部分,它基本是调用其他模块的函数来实现最终功能,其主要布骤包括:定义及初始化各个全局变量、打开socket动态库、设置接收和发送超时值、域名地址解析、分配内存、创建及初始化ICMP报文、发送ICMP请求报文、接收ICMP应答报文以及解读应答报文和输出Ping结果,最3后释放占用的资源其流程如下页图2.1所示。注释:(1)该模块并非只有处理还包括判断及输出判断结果的含义;(2)程序没运行一次就只能输出四行结果(前提是输入的地址有效),欲再次PING其他地址必须要重新启动程序。(3)输入时不能输入目标主机名,不然ping结果为TIMEOUT;开始定义及初始化各个全局变量判断WSAStartup函数是否调用成功输出调用失败否创建套接字以及设置socket接收超时,发送超时选项;是输入PING的IP地址解析输入内容,设置PING参数创建及填充ICMP数据报文判断是否已发送四次Break;发送,接收以及解析数据包输出PIING结果是结束清除残余否42.功能控制模块功能控制模块主要是为其他模块提供可调用的函数,该模块主要包括参数获取功能、计算ICMP数据报文检验和、清除SOCKET,ICMP包数据以及接受缓冲区、占用资源释放功能和显示用尸帮助功能。该模块一共包含三个函数来实现。,流程如图2.2所示。Checksum开始定义初始化cksum(size1)确定cksum及size大小是if(size)计算校验cksum,获得结果cksum+=*(UCHAR*)buffer;否结束Cleanup开始if(m_hSocket!=INVALID_SOCKE关闭套接字释放占用资源清除ICMP包数据以及接受缓冲区FWSACleanup();结束图2.2功能控制模块注释:a.illICMPData是由一系列的初始化的语句在流程图中不再画出;b.Cleanup()函数中的WSACleanup(),HeapFree(),closesocket()都是一些库函数。checksum()校验和函数是冗余校验的一种形式。它是通过错误检测方法,对经过空间(如通信)或者时间(如计算机存储)传送的数据的完整性进行检查的一种简单方法。53.数据报解析模块数据报解析模块提供了解读IP选项和解读IcMP报文的功能。从本机收到目的主机返回的1cMP回显应答报文,就开始逐个地解读IcMP报文,如果需要记录路由的情况下,IcMP解析函数将调用IP选项解读函数来实现IP路由的输出(但本程序没有此功能。该模块主要由DecodeICMPHeader一个函数来实现,而中间也会调用其它模块的相应函数。其流程图如图2.3:注释:a.判断是否为我们所要的数据报回应之前,还有一些判断回应多少内容的语句未呈现出;b.函数GetTickCount()是用来记录此时我机所处的现在时间(毫秒级);DecodeICMPHeader定义相关变量以及初始化;tick=GetTickCount();为我们所要的回应报文;是输出不是我们所要;tick0[icmpcount]=tick-icmphdr-timestamp;判断时间是否小于1msprintf(Replyfrom%s:dytes=%dtime1msicmp_seq=%d\n,inet_ntoa(from-sin_addr),printf(Replyfrom%s:dytes=%dtime=%dicmp_seq=%d\n,inet_ntoa(from-sin_addr),是是icmpcount++;结束结束否图2.3数据报解析模块6五、课程设计小结1.运行操作结果:在vc里运行之后界面:2.输入本机ip地址:3.输入网上ip看结果:4.但是当网络连不通时,就会出现下图结果7六、参考文献【1】VisualC++网络通信编程实用案例精选(第二版)曹衍龙刘海英编著;【2】Windows网络编程技术(美);七、附录(程序清单)#pragmacomment(lib,ws2_32.lib)#includewinsock2.h//创建套接字头文件#includews2tcpip.h#includestdio.h//标准输入输出函数#includestdlib.h//实用程序库函数#includestring.htypedefstructiphdr{unsignedinth_len:4;//头长度unsignedintversion:4;//IP版本unsignedcharservice;//服务类型unsignedshorttotal_len;//包的总长度unsignedshortident;//包标示身份unsignedshortfrag_and_flags;//标志unsignedcharttl;//包生命周期unsignedcharproto;//协议类型unsignedshortchecksum;//IP校验unsignedintsourceIP;//源IPunsignedintdestIP;//目标IP}IpHeader;#defineICMP_ECHO8//ICMP报文类型,回显请求#defineICMP_ECHOREPLY0//ICMP报文类型,回显应答#defineICMP_MIN8//最小的ICMP数据报大小typedefstructicmphdr{BYTEi_type;//ICMP报文类型BYTEi_code;//该类型中的代码号USHORTi_cksum;//校验和8USHORTi_id;//惟一的标识符USHORTi_seq;//序列号ULONGtimestamp;//时间戳}IcmpHeader;#defineDEF_PACKET_SIZE32//默认数据报大小#defineMAX_PACKET1024//最大的ICMP数据报大小#defineMAX_IP_HDR_SIZE60//最大IP头长度//初始化全局变量intdatasize=DEF_PACKET_SIZE;char*icmp_data=NULL;char*recvbuf=NULL;SOCKETm_hSocket=INVALID_SOCKET;char*lpdest=NULL;//填充ICMP数据报字段函数voidFillICMPData(char*icmp_data,intdatasize){IcmpHeader*icmp_hdr=NULL;char*datapart=NULL;icmp_hdr=(IcmpHeader*)icmp_data;icmp_hdr-i_type=ICMP_ECHO;icmp_hdr-i_code=0;icmp_hdr-i_id=(USHORT)GetCurrentProcessId();icmp_hdr-i_cksum=0;icmp_hdr-i_seq=0;datapart=icmp_data+sizeof(IcmpHeader);}//校验和函数USHORTchecksum(USHORT*buffer,intsize){unsignedlongcksum