基于C语言实现的Ping程序

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

【前言】Ping是用于测试网络连接量的程序,利用它可以检查网络是否能够连通。Ping程序的实现原理非常简单,即发送一个ICMP回声请求消息给目的地并报告是否收到所希望的ICMP回声应答。本文采用C语言编写一个ing功能的程序。0.ICMP协议简介ICMP是(InternetControlMessageProtocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。ICMP协议是一种面向连接的协议,用于传输出错报告控制信息。它是一个非常重要的协议,它对于网络安全具有极其重要的意义。它是TCP/IP协议族的一个子协议,属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。ICMP提供一致易懂的出错报告信息。发送的出错报文返回到发送原数据的设备,因为只有发送设备才是出错报文的逻辑接受者。发送设备随后可根据ICMP报文确定发生错误的类型,并确定如何才能更好地重发失败的数据报。但是ICMP唯一的功能是报告问题而不是纠正错误,纠正错误的任务由发送方完成。我们在网络中经常会使用到ICMP协议,比如我们经常使用的用于检查网络通不通的Ping命令(Linux和Windows中均有),这个“Ping”的过程实际上就是ICMP协议工作的过程。还有其他的网络命令如跟踪路由的Tracert命令也是基于ICMP协议的。ICMP报文分为两种,一是错误报告报文,二是查询报文。每个ICMP报头均包含类型、编码和校验和这三项内容,长度为8位,8位和16位,其余选项则随ICMP的功能不同而不同。这两种ICMP类型报头格式如下:1.程序源代码/*********************************************************功能:实现PING功能*环境:GCC-4.2.4*作者:YSQ-NJUST,yushengqiangyu@163.com*备注:自由软件,主要用于学习、交流、共享。*******************************************************/#includestdio.h#includeunistd.h#includestdlib.h#includestring.h#includeerrno.h#includenetdb.h#includesys/time.h#includesys/types.h#includesys/socket.h#includenetinet/ip_icmp.h#includenetinet/in.h#includearpa/inet.h#defineE_FAILD_FD-1#defineICMP_DATA_LEN20/*ICMP负载长度*/#defineICMP_ECHO_MAX4/*ECHO-REQUEST报文发送次数*/#defineICMP_REQUEST_TIMEOUT2/*超时时间间隔*//*ICMP报文发送与接收缓存*/staticunsignedcharaucSendBuf[1024*1024]={0};staticunsignedcharaucRecvBuf[1024*1024]={0};/*结构体定义*/typedefstructtagIcmpStatic{unsignedintuiSendPktNum;unsignedintuiRcvPktNum;floatfMinTime;floatfMaxTime;floatfArgTime;}ICMP_STATIC_S;/*全局数据结构*/ICMP_STATIC_Sg_stPktStatic;/*ICMP报文统计*/structtimevalstSendTime={0};/*ECHO-REQUEST报文发送时间*/structtimevalstRcvTime={0};/*ECHO-REPLY报文接收时间*//*输出报文统计信息*/voidshowStatic(constICMP_STATIC_S*pstStInfo){unsignedintuiSend,uiRecv;uiSend=pstStInfo-uiSendPktNum;uiRecv=pstStInfo-uiRcvPktNum;printf(\n***PINGStatistics***);printf(\nPackets:Send=%u,Recveived=%u,Lost=%u,uiSend,uiRecv,uiSend-uiRecv);printf(\nTime:Minimum=%.1fms,Maximum=%.1fms,Average=%.2fms\n,pstStInfo-fMinTime,pstStInfo-fMaxTime,pstStInfo-fArgTime);}/*计算时间差,返回时间以毫秒为单位*/unsignedinttimeSub(conststructtimeval*pstOut,conststructtimeval*pstIn){unsignedintuiSec=0;intiUsec=0;uiSec=pstOut-tv_sec-pstIn-tv_sec;iUsec=pstOut-tv_usec-pstIn-tv_usec;if(0iUsec){iUsec+=1000000;uiSec--;}returnuiSec*1000+(unsignedint)(iUsec/1000);}/*校验和计算*/unsignedshortcalcIcmpChkSum(constvoid*pPacket,intiPktLen){unsignedshortusChkSum=0;unsignedshort*pusOffset=NULL;pusOffset=(unsignedshort*)pPacket;while(1iPktLen){usChkSum+=*pusOffset++;iPktLen-=sizeof(unsignedshort);}if(1==iPktLen){usChkSum+=*((char*)pusOffset);}usChkSum=(usChkSum16)+(usChkSum&0xffff);usChkSum+=(usChkSum16);return~usChkSum;}/*ICMP报文填充*/intnewIcmpEcho(constintiPacketNum,constintiDataLen){structicmp*pstIcmp=NULL;memset(aucSendBuf,0,sizeof(aucSendBuf));pstIcmp=(structicmp*)aucSendBuf;pstIcmp-icmp_type=ICMP_ECHO;pstIcmp-icmp_code=0;pstIcmp-icmp_seq=htons((unsignedshort)iPacketNum);pstIcmp-icmp_id=htons((unsignedshort)getpid());pstIcmp-icmp_cksum=0;pstIcmp-icmp_cksum=calcIcmpChkSum(pstIcmp,iDataLen+8);returniDataLen+8;}/*解析ECHO-REPLY响应报文*/intparseIcmp(conststructsockaddr_in*pstFromAddr,char*pRecvBuf,constintiLen){intiIpHeadLen=0;intiIcmpLen=0;structip*pstIp=NULL;structicmp*pstIcmpReply=NULL;pstIp=(structip*)pRecvBuf;iIpHeadLen=pstIp-ip_hl2;pstIcmpReply=(structicmp*)(pRecvBuf+iIpHeadLen);/*报文长度非法*/iIcmpLen=iLen-iIpHeadLen;if(8iIcmpLen){printf([Error]BadICMPEcho-reply\n);return-1;}/*报文类型非法*/if((pstIcmpReply-icmp_type!=ICMP_ECHOREPLY)||(pstIcmpReply-icmp_id!=htons((unsignedshort)getpid()))){return-1;}sleep(1);printf(%dbytesreplyfrom%s:icmp_seq=%uTime=%dmsTTL=%d\n,iIcmpLen,inet_ntoa(pstFromAddr-sin_addr),ntohs(pstIcmpReply-icmp_seq),timeSub(&stRcvTime,&stSendTime),pstIp-ip_ttl);return1;}/*Echo响应报文接收*/voidrecvIcmp(constintfd){intiRet=0;intiRecvLen=0;unsignedintuiInterval=0;socklen_tfromLen=sizeof(structsockaddr_in);structsockaddr_instFromAddr={0};/*清空接收缓存,并准备接收响应报文*/memset(aucRecvBuf,0,1024*1024);iRecvLen=recvfrom(fd,(void*)aucRecvBuf,sizeof(aucRecvBuf),0,(structsockaddr*)&stFromAddr,&fromLen);gettimeofday(&stRcvTime,NULL);if(0iRecvLen){if(EAGAIN==errno){/*请求超时*/printf(Requesttimeout.\n);g_stPktStatic.fMaxTime=~0;}else{/*接收数据包出错*/perror([Error]ICMPReceive);}return;}/*获取统计参数*/g_stPktStatic.uiRcvPktNum++;uiInterval=timeSub(&stRcvTime,&stSendTime);g_stPktStatic.fArgTime=(g_stPktStatic.fArgTime*(g_stPktStatic.uiSendPktNum-1)+uiInterval)/g_stPktStatic.uiSendPktNum;if(uiIntervalg_stPktStatic.fMinTime){g_stPktStatic.fMinTime=uiInterval;}if(uiIntervalg_stPktStatic.fMaxTime){g_stPktStatic.fMaxTime=uiInterval;}/*解析ICMP响应报文*/iRet=parseIcmp(&stFromAddr,(char*)aucRecvBuf,iRecvLen);if(0iRet){return;}}/*发送ICMP报文*/voidsendIcmp(constintfd,conststructsockaddr_in*pstDestAddr){unsignedcharucEchoNum=0;intiPktLen=0;intiRet=0;while(ICMP_ECHO_MAXucEchoNum){iPktLen=newIcmpEcho(ucEchoNum,ICMP_DATA_LEN);

1 / 11
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功