版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、07网络工程本制作人:北-624寝室负责人:赖文斌第四篇网络编程第九章ping程序设计ping命令是使用频率极高的一个网络测试命令,用以测试从一个主机到另一个主机间的网络上否可达。windows自带的ping命令具有强大的功能,它有很多选项用于实现不同的测试目的。本章模仿windows的ping命令,用c语言实现了一个简单的命令。本章着重讲述ping命令的实现原理和现的ping命令进行扩展,的方法。c语言的网络编程方法。读者可以在本章的基础上,对本章实开发出功能更强大、更完善的ping命令,9.1设计目的并进一步掌握网络编程本章通过设计Ping程序,讲解本章涉及很多网络编程函数和编程技巧。Pi
2、ng程序的实现原理,并初步讲解了包括库文件的导入;c语言网络编程技术。winsock的初始化、注销;socket的创建、关闭;设置socket选项;根据主机名获取IP地址;从堆中分配一定数量的空间、释放从堆中分配的空间;获取当前进程ID号;数据报的发送;数据报的接等通过本程序的训练,使读者对网络编程有一定的了解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。本章用c语言实现的况,程序还提供了几个选项以实现不同的功能。(1)实现ping功能。程序能实现基本的答报文。(2)能记录路由。程序提供了“(3)能输出指定条数的记录。程序提供了“(4)能按照指定大小输出每
3、条记录。程序提供了“9.2功能描述ping命令,能用于测试一个主机到另一个主机间的联通情ping操作,发送ICMP回显请求报文,接收显应-r”选项,用以记录从源主机到目的主机的路由。-n”选项,用以输出指定条数的记录。datasize”选项,用以指定输出的数据报的大小。(5)能输出用户帮助。程序提供了用户帮助,显示程序提供的选项以及选项格式等。9.3总体设计9.3.1功能模块设计1.功能模块图本系统共有4个模块,分别是初始化模块、功能控制模块、数据控制模块、数据报解读模块和ping测试模块,如图9.1所示。各模块功能描述如下。图9.1系统模块图(1) 初始化模块。改模块用于初始化各个全局变量,
4、为全局变量赋初始值;初始化,加载库。(2) 功能控制模块。改模块是被其它模块调用,其功能包括获取参数、计算校验和填充数据报文、释放占用资源和显示用户帮助。(3) 数据报解读模块。改模块用于解读接收到的报文和选项。(4) 测试模块。改模块是本程序的核心模块,调用其他模块实现其功能,主要是实现的功能系统执行的流程图9.2所示。程序首先调用IniPing()函数初始化各全局变量,然后GetArgments()函数获取用户输入的参数,检查用户输入的参数,如果参数不正确或者没有输入参数,则显示用户帮助信息(Userhelp),并结束程序;如果参数正确,则对指定目的地执行Ping命令,如果Ping通,则显
5、示Ping结果并释放占用资源,如果没有Ping通,则报告错误信息,并释放占用资源。图9.2系统流程图3.参数获取(GetArgments()函数)流程图获取的参数包括“-r”(记录路由)、“-n”(记录条数程序,任意的整数)和datasize(数据报大小)。程序首先判断每一个参数的第一字符,如果第一个字符是“-”(短横线),则认为是“-r”或者“-n”中的一个,然后作进一步判断。如果该参数的第二个字符是数字,则判断该参数为记录的条数,如果该参数的第二个字符是“r”,则判断该参数为“-r”,用于记录路由;如果参数的第一个字符是数字,则认为参数是IP地址;或者datasize,然后作进一步的判断。
6、如果该参数中不存在非数字的字符,则判断该参数为datasize;如果存在非数字的字符,则判断该参数为IP地址;其他情况则判断为主机名。参数获取的流程如图9.3所示。Argc=l是数字?是数字?该参数中有是还有参数?非数字字是?该参数表示该参数表示IP地址数据报大小转换成十进制记录到全局变量packetNUM检查第一i个参数的第二个字符检查第一i个参数的第一个字符该参数表示要获取的记录数设标志位RecordFlag为ture开始记录到变量Lpdest中该参数表示主机名记录到变量Datasize中记录到变量Lpdest中显示用户帮助I=i+1结束图9.3参数获取流程图4.ping()ping()函
7、数是本程序的核心部分它调用其他模块的函数来实现,其主要步骤包括创建接字,设置路由选项(如果需要的话)、设置接收和发送超时值、名字解析(如果需要的话)、分配内存、创建ICMP报文、发送ICMP请求报文、接收ICMP应答报文和解读ICMP报文。其执行流程如图9.4所示。创建成功?记录路由?设置成功?名字解析?获取成功?分配成功发送成功?超时发送?输出失败信息为每个ICMP设置路由选项设置目的地址各项字段根据ICMP报文大小分配内存设置接收和发送超时值创建ICMP报文发送ICMP请求接收ICMP应答根据主机名获取各种参数输出超时发送创建原始套接字图9.4Ping函数流程图9.3.2数据结构设计本程序
8、定义了3个结构体:-iphdr、-icmphdr、和-ipotionhdr,分别用于存放IP报头信息、ICMP报头信息和IP路由选项信息。1.定义IP报头结构体Typedefstruct_iphdr1Unsignedinth_len:4;Unsignedintversion:4;Unsignedchartos;Unsignedshorttotal_leUnsignedshortident;Unsignedshortfrag_flags;Unsignedcharttl;Unsignedchorproto;Unsignedshortchecksum;UnsignedintsourceIP;Unsi
9、gnedintdestIP;IpHeader;其中各字段表示意义如下。h-len:4:表示IP报头长度,首部长度指的是首部占32bit字的数目,包括任何选项。由于它是一个4bit字段,因此首部最长为60个字节,不包括任何选项的IP报头是20个字节。Version:4:表示IP的版本号,这里表示Ipv4.。Top:表示服务的类型,可以表示最小时延,最大吞吐量,最高可靠性和最小费用。Totallen:整个IP数据报的总长度。Ident:唯一的标识符,标识主机发送的每一份数据报。Frag-flags:分段标志,表示过长的数据报是否要分段。Ttl:Proto:Checksum:生存期,表示数据报可以经
10、过的最多路由器数。协议类型(TCP、UDP等)。校验和。sourceIP:源IP地址。destIP:目的IP地址。2.定义ICMP报头结构体TypedefstructicmphdrBYTEi_type;BYTEi_code:USHORTUSHORTUSHORTULONGi_cksum;i_id;i_seq;timestamp;IcmpHeader;其中各字段表示意义如下。I_tye:DDDD报文类型。I_code:该类型中的代码号,一种ICMP报文的类型号和该类型中的代码号共同决定。、I_cksum:I_seq:校验和。序列号,序列号从0开始,每发送一次新的回显请求就加1.Timestamp:
11、时间。3.定义IP选项结构体Typedefstruct_ipoptionhdrUnsignedUnsignedUnsignedUnsignedcharcode;charlen;charptr;loangaddr9;IcmpHeader;其中各字段表示意义如下。Code:Len:Ptr:addr9:指明IP选项类型,对于路由记录选项,它的值是7。选项头长度。地址指针字段,是一个基于1的指针,指向存放下一个IP地址的位置。记录的Ip地址列表,由于IP首部中选项的空间有限,所以可以记录的Ip地址最多是9个。9.331) IntPing()函数原型:voidIntPing()IntPing()函数用于
12、初始化ping所需的全局变量,为各个变量赋初始值。2) userHelp()函数原型:voiduserHelp()userHeIp()函数用于显示用户帮助信息。当程序检查到参数错误或者没有必要的参数(如主机IP地址或者主机名)时,则会调用此函数显示帮助信息。3) GetArgments()函数原型:voidGetArgments(intargc,char*argv)GetArgments()函数用于获取用户提交的参数。其中argc表示获取的参数个数,argv用于存储获取的参数,这两个形参和主函数中的形参表示的意义一样的。4) checkSum()函数原型:USHORTcheckSum(USHO
13、RT*buffer,intsize)checkSum()函数用于计算校验和。计算过程是首先把数据报头中的校验和字段设置为0,然后对首部中每个16bit进行二字段进制反码求和(整个首部看成是由一串16bit的字组成),结果存在校验和字段中。其中buffer用于存放ICMP数据,size表示ICMP报文大小。5) FillCMPData()函数原型:voidFillCMPData()FillCMPData()函数用于填充ICMP数据报中各个字段。其中icmp_data表示ICMP数据,datasize表示ICMP报文大小。6) reeRes()函数原型:voidreeRes()reeRes()函数
14、用于释放占用的资源,包括关闭初始化socket调用的函数的、关闭创建的socket和释放分配的内存等。7) DecodeIPOptions()函数原型:voidDecodeIPOptions()DecodeIPOptions()函数用于解读IP选项,从中读出从源主机到目的主机经过的路由,并输出路由信息。Buf表示存放接收到的ICMP报文的缓冲区,bytes表示接收到的字节数。8) DecodelICMPHeader()函数原型:voidDecodelICMPHeader(char*buf,intbytes,SOCKADDR_IN*from)DecodelICMPHeader()函数用于解读IC
15、MP报文信息。Buf表示存放接收到的ICMP报文的缓冲区,bytes表示接收到的字节数,from表示发送ICMP回显应答的主机IP地址。9) PingTest()函数原型:voidPingTest(inttimeout)PingTest()函数用于进行Ping操作。其中timeout表示设定的发送超时值。9.4程序实现9.1.4源码分析1.程序预处理/*导入库文件*/#pragmacomment(lib,"ws2_32.lib")/*加载头文件*/#include<winsock2.h>#include<ws2tcpip.h>#include<
16、stdio.h>#include<stdlib.h>#include<math.h>/*定义常量*/*表示要记录路由*/#defineIP_RECORD_ROUTE0x7/*默认数据报大小*/#defineDEF_PACKET_SIZE32/*最大的ICMP数据报大小*/#defineMAX_PACKET1024/*最大IP头长度*/#defineMAX_IP_HDR_SIZE60/*ICMP报文类型,回显请求*/#defineICMP_ECHO8/*ICMP报文类型,回显应答*/#defineICMP_ECHOREPLY0/*最小的ICMP数据报大小*/#def
17、ineICMP_MIN8/*自定义函数原型*/voidInitPing();voidUserHelp();voidGetArgments(intargc,char*argv);USHORTCheckSum(USHORT*buffer,intsize);voidFillICMPData(char*icmp_data,intdatasize);voidFreeRes();voidDecodeIPOptions(char*buf,intbytes);voidDecodeICMPHeader(char*buf,intbytes,SOCKADDR_IN*from);voidPingTest(inttim
18、eout);/*IP报头字段数据结构*/typedefstruct_iphdrunsignedinth_len:4;unsignedintversion:4;unsignedchartos;unsignedshorttotal_len;unsignedshortident;unsignedshortfrag_flags;unsignedcharttl;unsignedcharproto;unsignedshortchecksum;unsignedintsourceIP;unsignedintdestIP;IpHeader;/*ICMP报头字段数据结构*/typedefstruct_icmphd
19、rBYTEi_type;BYTEi_code;USHORTi_cksum;USHORTi_id;USHORTi_seq;ULONGtimestamp;IcmpHeader;/*IP报头长度*/*IP的版本号*/*服务的类型*/*数据报总长度*/*惟一的标识符*/*分段标志*/*生存期*/*协议类型(TCP、UDP等)*/*校验和*/*源IP地址*/*目的IP地址*/*ICMP报文类型*/*该类型中的代码号*/*校验和*/*惟一的标识符*/*序列号*/*时间戳*/*IP选项头字段数据结构*/typedefstruct_ipoptionhdrunsignedcharunsignedcharunsi
20、gnedcharunsignedlongcode;len;ptr;addr9;/*选项类型*/*选项头长度*/*地址偏移长度*/*记录的IP地址列表*/IpOptionHeader;/*定义全局变量*/SOCKETm_socket;IpOptionHeaderIpOption;SOCKADDR_INDestAddr;SOCKADDR_INSourceAddr;char*icmp_data;char*recvbuf;USHORTseq_no;char*lpdest;intdatasize;BOOLRecordFlag;doublePacketNum;BOOLSucessFlag;2.初始化模块/
21、*初始化变量函数*/voidInitPing()WSADATAwsaData;icmp_data=NULL;seq_no=0;recvbuf=NULL;RecordFlag=FALSE;lpdest=NULL;datasize=DEF_PACKET_SIZE;PacketNum=5;SucessFlag=FALSE;/*Winsock初始化*/if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)/*如果初始化不成功则报错,GetLastError()返回发生的错误信息*/printf("WSAStartup()failed:%dn",G
22、etLastError();return;m_socket=INVALID_SOCKET;3.功能控制模块/*显示信息函数*/voidUserHelp()printf("UserHelp:ping-r<host>datasizen");printf("-rrecordrouten");printf("-nrecordamountn");printf("hostremotemachinetopingn");printf("datasizecanbeupto1KBn");ExitProc
23、ess(-1);/*获取ping选项函数*/voidGetArgments(intargc,char*argv)inti;intj;intexp;intlen;intm;/*如果没有指定目的地地址和任何选项*/if(argc=1)printf("nPleasespecifythedestinationIPaddressandthepingoptionasfollow!n");UserHelp();for(i=1;i<argc;i+)len=strlen(argvi);if(argvi0='-')/*选项指示要获取记录的条数*/if(isdigit(ar
24、gvi1)PacketNum=0;for(j=len-1,exp=0;j>=1;j-,exp+)/*根据argvij中的ASCII值计算要获取的记录条数(十进制数)*/PacketNum+=(double)(argvij-48)*pow(10,exp);elseswitch(tolower(argvi1)/*选项指示要获取路由信息*/case'r':RecordFlag=TRUE;break;/*没有按要求提供选项*/default:UserHelp();break;/*参数是数据报大小或者IP地址*/elseif(isdigit(argvi0)for(m=1;m<
25、len;m+)if(!(isdigit(argvim)/*是IP地址*/lpdest=argvi;break;/*是数据报大小*/elseif(m=len-1)datasize=atoi(argvi);/*参数是主机名*/elselpdest=argvi;/*求校验和函数*/USHORTCheckSum(USHORT*buffer,intsize)unsignedlongcksum=0;while(size>1)cksum+=*buffer+;size-=sizeof(USHORT);if(size)cksum+=*(UCHAR*)buffer;/*对每个16bit进行二进制反码求和*/
26、cksum=(cksum>>16)+(cksum&0xffff);cksum+=(cksum>>16);return(USHORT)(cksum);/*填充ICMP数据报字段函数*/voidFillICMPData(char*icmp_data,intdatasize)IcmpHeader*icmp_hdr=NULL;char*datapart=NULL;icmp_hdr=(IcmpHeader*)icmp_data;/*ICMP报文类型设置为回显请求*/icmp_hdr->i_type=ICMP_ECHO;icmp_hdr->i_code=0;/*
27、获取当前进程IP作为标识符*/icmp_hdr->i_id=(USHORT)GetCurrentProcessId();icmp_hdr->i_cksum=0;icmp_hdr->i_seq=0;datapart=icmp_data+sizeof(IcmpHeader);/*以数字0填充剩余空间*/memset(datapart,'0',datasize-sizeof(IcmpHeader);/*释放资源函数*/voidFreeRes()/*关闭创建的套接字*/if(m_socket!=INVALID_SOCKET)closesocket(m_socket);
28、/*释放分配的内存*/HeapFree(GetProcessHeap(),0,recvbuf);HeapFree(GetProcessHeap(),0,icmp_data);/*注销WSAStartup()调用*/WSACleanup();return;4.数据报解读模块/*解读IP选项头函数*/voidDecodeIPOptions(char*buf,intbytes)IpOptionHeader*ipopt=NULL;IN_ADDRinaddr;inti;HOSTENT*host=NULL;/*获取路由信息的地址入口*/ipopt=(IpOptionHeader*)(buf+20);pri
29、ntf("RR:");for(i=0;i<(ipopt->ptr/4)-1;i+)inaddr.S_un.S_addr=ipopt->addri;if(i!=0)printf("");/*根据IP地址获取主机名*/host=gethostbyaddr(char*)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET);/*如果获取到了主机名,则输出主机名*/if(host)printf("(%-15s)%sn",inet_ntoa(inaddr),hos
30、t->h_name);/*否则输出IP地址*/elseprintf("(%-15s)n",inet_ntoa(inaddr);return;/*解读ICMP报头函数*/voidDecodeICMPHeader(char*buf,intbytes,SOCKADDR_IN*from)IpHeader*iphdr=NULL;IcmpHeader*icmphdr=NULL;unsignedshortiphdrlen;DWORDtick;staticinticmpcount=0;iphdr=(IpHeader*)buf;/*计算IP报头的长度*/iphdrlen=iphdr-&
31、gt;h_len*4;tick=GetTickCount();/*如果IP报头的长度为最大长度(基本长度是20字节),则认为有IP选项,需要解读IP选项*/if(iphdrlen=MAX_IP_HDR_SIZE)&&(!icmpcount)/*解读IP选项,即路由信息*/DecodeIPOptions(buf,bytes);/*如果读取的数据太小*/if(bytes<iphdrlen+ICMP_MIN)printf("Toofewbytesfrom%sn",inet_ntoa(from->sin_addr);icmphdr=(IcmpHeader
32、*)(buf+iphdrlen);/*如果收到的不是回显应答报文则报错*/if(icmphdr->i_type!=ICMP_ECHOREPLY)printf("nonechotype%drecvdn",icmphdr->i_type);return;/*核实收到的ID号和发送的是否一致*/if(icmphdr->i_id!=(USHORT)GetCurrentProcessId()printf("someoneelse'spacket!n");return;SucessFlag=TRUE;/*输出记录信息*/printf(&qu
33、ot;%dbytesfrom%s:",bytes,inet_ntoa(from->sin_addr);printf("icmp_seq=%d.",icmphdr->i_seq);printf("time:%dms",tick-icmphdr->timestamp);printf("n");icmpcount+;return;5.Ping测试模块/*ping函数*/voidPingTest(inttimeout)intret;intreadNum;intfromlen;structhostent*hp=NUL
34、L;NULL,/*创建原始套接字,该套接字用于ICMP协议*/m_socket=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,0,WSA_FLAG_OVERLAPPED);/*如果套接字创建不成功*/if(m_socket=INVALID_SOCKET)printf("WSASocket()failed:%dn",WSAGetLastError();return;/*若要求记录路由选项*/if(RecordFlag)/*IP选项每个字段用0初始化*/ZeroMemory(&IpOption,sizeof(IpOption);/*为每
35、个ICMP包设置路由选项*/IpOption.code=IP_RECORD_ROUTE;IpOption.ptr=4;IpOption.len=39;ret=setsockopt(m_socket,IPPROTO_IP,IP_OPTIONS,(char*)&IpOption,sizeof(IpOption);if(ret=SOCKET_ERROR)printf("setsockopt(IP_OPTIONS)failed:%dn",WSAGetLastError();/*设置接收的超时值*/readNum=setsockopt(m_socket,SOL_SOCKET,
36、SO_RCVTIMEO,(char*)&timeout,sizeof(timeout);if(readNum=SOCKET_ERROR)printf("setsockopt(SO_RCVTIMEO)failed:%dn",WSAGetLastError();return;/*设置发送的超时值*/timeout=1000;readNum=setsockopt(m_socket,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout);if(readNum=SOCKET_ERROR)printf("s
37、etsockopt(SO_SNDTIMEO)failed:%dn",WSAGetLastError();return;/*用0初始化目的地地址*/memset(&DestAddr,0,sizeof(DestAddr);/*设置地址族,这里表示使用IP地址族*/DestAddr.sin_family=AF_INET;if(DestAddr.sin_addr.s_addr=inet_addr(lpdest)=INADDR_NONE)/*名字解析,根据主机名获取IP地址*/if(hp=gethostbyname(lpdest)!=NULL)/*将获取到的IP值赋给目的地地址中的相应
38、字段*/memcpy(&(DestAddr.sin_addr),hp->h_addr,hp->h_length);/*将获取到的地址族值赋给目的地地址中的相应字段*/DestAddr.sin_family=hp->h_addrtype;printf("DestAddr.sin_addr=%sn",inet_ntoa(DestAddr.sin_addr);/*获取不成功*/elseprintf("gethostbyname()failed:%dn",WSAGetLastError();return;/*数据报文大小需要包含ICMP
39、报头*/datasize+=sizeof(IcmpHeader);/*根据默认堆句柄,从堆中分配MAX_PACKET内存块,新分配内存的内容将被初始化为0*/icmp_data=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);recvbuf=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);/*如果分配内存不成功*/if(!icmp_data)printf("HeapAlloc()failed:%dn",GetLastError();return;/*创建ICMP报文*/memset(icmp_data,0,MAX_PACKET);FillICMPData(icmp_data,datasize);w
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公司收款内控制度
- 工程资金内控制度
- 纪工委内控制度汇编
- 车辆管理内控制度
- 科室协作内控制度
- 工伤保险内控制度
- 8.1 认识生命(议题式教学设计)2025-2026学年七年级道德与法治上册+教学设计+练习(统编版2024)
- 医保信息化内控制度
- 股份回购内控制度
- 宝鸡财政内控制度
- DBJ-T 15-30-2022 铝合金门窗工程技术规范
- 2024届广东省高三三校12月联考英语试题及答案
- 城市设计编制标准 DG-TJ08-2402-2022
- 粉煤灰在高速公路基层中的应用
- 教学设计中的学科整合与跨学科学习
- 2024年广东省粤科金融集团有限公司招聘笔试参考题库含答案解析
- 消防设施维保投标方案(技术方案)
- 设备综合效率OEE统计表(使用)
- WATERS公司的UPLCTQD培训资料MS7校正课件
- 【超星尔雅学习通】航空与航天网课章节答案
- 2022年福州大学计算机科学与技术专业《操作系统》科目期末试卷B(有答案)
评论
0/150
提交评论