通信专业方向设计课程设计-网络丢包率测量程序设计_第1页
通信专业方向设计课程设计-网络丢包率测量程序设计_第2页
通信专业方向设计课程设计-网络丢包率测量程序设计_第3页
通信专业方向设计课程设计-网络丢包率测量程序设计_第4页
通信专业方向设计课程设计-网络丢包率测量程序设计_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

西南科技大学通信专业方向设计课程名称:通信工程方向设计设计名称:网络丢包率测量程序设计姓名:学号:班级:指导教师:起止日期:西南科技大学信息工程学院制课程设计任务书学生班级:学生姓名:学号:设计名称:起止日期:指导教师:设计要求:1.设计一个小型局域网,并给出拓扑结构图;2.完成局域网的构建,给出相应的设备清单和参数设置;3.使用RAW模式的SOCKET编程,完成PING程序设计,给出调试结果4.编写客户程序和服务器程序,实现数据传输5.提供设计流程图和程序清单6.撰写论文(5000字以上)课程设计学生日志时间设计内容了解题目及设计要求。查阅相关资料,确定设计方案。编写及调试程序。撰写课程设计报告。进行答辩。课程设计考勤表周星期一星期二星期三星期四星期五课程设计评语表指导教师评语:成绩:指导教师:年月日PING程序的设计设计目的和意义要求设计并构建一个局域网,通过在这个计算机网络环境中的实际操作,对现代计算机网络的基本功能和体系结构进一步了解。通过一个简单的PING程序的设计和实现,理解TCP/IP协议的工作机制和编程方法;掌握计算机网络应用层协议的基本实现技术。通过在计算机网络环境中的实际操作,对现代计算机网络基本功能和体系结构进一步了解。通过一个简单的PING程序的设计和实现,理解TCP/IP协议的工作机制和编程方法;掌握计算机网络应用层协议的基本实现技术及各种协议的结构。掌握RAW模式的SOCKET编程的方法。设计原理1、PING的工作原理ping程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接。ping使用的是ICMP协议,它发送ICMP回送请求消息给目的主机。ICMP协议规定:目的主机必须返回ICMP回送应答消息给源主机。如果源主机在一定时间内收到应答,则认为主机可达。ICMP协议通过IP协议发送的,IP协议是一种无连接的,不可靠的数据包协议。因此,保证数据送达的工作应该由其他的模块来完成。其中一个重要的模块就是ICMP(网络控制报文)协议。当传送IP数据包发生错误--比如主机不可达,路由不可达等等,ICMP协议将会把错误信息封包,然后传送回给主机。给主机一个处理错误的机会,这也就是为什么说建立在IP层以上的协议是可能做到安全的原因。ICMP数据包由8bit的错误类型和8bit的代码和16bit的校验和组成。而前16bit就组成了ICMP所要传递的信息。PING利用ICMP协议包来侦测另一个主机是否可达。原理是用类型码为0的ICMP发请求,受到请求的主机则用类型码为8的ICMP回应。ping程序来计算间隔时间,并计算有多少个包被送达。用户就可以判断网络大致的情况。随着互联网的安全意识的增加,出现了访问控制清单的路由器和防火墙,由于ICMP报文是在IP数据包中被传输的,而到达一台主机不仅取决于IP层是否到达,还取决于使用何种协议和端口。所以在现在的情况下,即时Ping不通某台机器,但也有可能FTP登陆到这台机器,或者通过来浏览这台机器上的Web页面。2.利用ping命令检查网络故障事实上,无论是什么类型的故障诊断工具,在一些特殊网络故障面前都会显得无能为力;此时,我们所能做的就是依靠自己,从使用Ping命令开始,手工逐步排查故障原因。

首先对本地工作站的循环地址进行ping测试。当遇到一些无法直接找到故障原因的特殊网络故障时,我们首先需要使用Ping命令测试一下本地工作站的循环地址能否被正常Ping通,倘若该地址无法被正常Ping通的话,那么说明本地工作站的TCP/IP协议程序受到了破坏,或者网卡设备发生了损坏。

此时,我们不妨打开本地工作站系统的设备管理器窗口,从中找到网卡设备选项,并用鼠标右键单击该选项,从弹出的快捷菜单中执行“属性”命令,打开网卡设备的属性设置窗口,在该窗口的“常规”标签页面中我们就能看到当前的网卡工作状态是否正常了。

当发现网卡工作状态正常的话,那很有可能是本地工作站的TCP/IP协议程序受到了破坏,此时我们不妨打开本地连接属性设置窗口,选中并删除该设置窗口中的TCP/IP协议选项,之后再重新安装一下TCP/IP协议程序,相信这么一来本地工作站的循环地址就能被正常Ping通了。

其次对本地工作站的IP地址进行ping测试。在确认地址能够被Ping通的情况下,我们继续使用Ping命令测试一下本地工作站的静态IP地址是否能被正常Ping通,倘若该地址不能被正常Ping通的话,那么说明本地工作站的网卡参数没有设置正确,或者网卡驱动程序不正确,也有可能是本地的路由表受到了破坏。

此时我们可以重新检查一下本地工作站的网络参数是否设置正确,如果在网络参数设置正确的情况下仍然无法Ping通本地IP地址的话,我们最好重新安装一下网卡设备的原装驱动程序,相信这么一来我们就能正确Ping通本地工作站的静态IP地址了。一旦本地工作站的静态IP地址被顺利Ping通的话,那就表明本地工作站已经能够加入到局域网网络中了。

接着对本地局域网的默认网关地址进行ping测试。由于本地工作站是通过网关与局域网中的其他工作站进行相互通信的,只有本地工作站与默认网关之间连接正常,才能确保本地工作站与其他工作站通信正常。倘若网关地址能被正常Ping通的话,那就表明本地工作站可以与局域网中的其他工作站进行正常通信。

要是Ping命令操作不成功的话,那很有可能是网关设备自身存在问题,或者是本地工作站与网关之间的线路连接不正常,也有可能是本地工作站与网关没有设置成同一个子网中。此时,我们可以先用专业的线缆测试工具测试一下网络线缆的连通性,在线缆连通性正常的情况下,再检查本地工作站的网络参数是否与网关的参数设置成同一个子网中。

倘若网络参数设置正确的话,我们再从其他工作站Ping一下网关地址,以便确认网关自身是否存在原因,如果局域网中的其他工作站也无法Ping通网关的话,那多半是网关设备自身存在问题,这个时候我们只要将故障排查重点锁定在网关设备上就可以了。

下面对局域网中任意一台远程工作站的IP地址进行ping测试,以便检验本地工作站能否通过网关设备与局域网中的其他工作站进行通信。要是我们发现远程工作站的IP地址无法Ping通的话,那很有可能是远程工作站自身无法响应,或者是远程工作站与网关设备之间的线路连接出现了问题,此时我们可以将网络故障的排查重点聚焦到远程工作站上或者是局域网的网络设备上。

最后对局域网的远程工作站主机名称进行ping测试。在确认能够Ping通远程工作站IP地址的情况下,仍然出现无法访问远程工作站内容的时候,我们就有必要进行这一项测试操作。如果该主机名称无法被Ping成功的话,那很有可能是DNS解析出现了问题,而不是网络连接发生了故障,此时我们不妨把故障检查重点锁定在DNS服务器上。

3、RAW模式的SOCKET编程

PING程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。为了实现直接对IP和ICMP包进行操作,设计中使用RAW模式的SOCKET编程。RAWSOCKET,即原始套接字,可以接收本机网卡上的数据帧或者数据包,对与监听网络的流量和分析是很有作用的。要使用原始套接字,必须经过创建原始套接字、设置套接字选项和创建并填充相应协议头这三个步骤,然后用send、WSASend等函数将组装好的数据发送出去。接收的过程也很相似,只是需要用recv或WSARecv等函数接收数据。详细设计步骤IP、ICMP头部结构IP是英文InternetProtocol(网络之间互连的协议)的缩写,中文简称为“网协”,也就是为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议就可以与因特网互连互通。IP地址具有唯一性,根据用户性质的不同,可以分为5类。另外,IP还有进入防护,知识产权,指针寄存器等含义。/******************IP头部定义******************/typedefstruct_iphdr{unsignedcharh_len:4; //头长度,占4bitunsignedcharversion:4; //IP版本,占4bitunsignedchartos; //服务类型unsignedshorttotal_len; //包的总长度unsignedshortident; //包标示身份unsignedshortfrag_and_flags; //标志unsignedcharttl; //包生命周期unsignedcharproto; //协议类型unsignedshortchecksum; //IP校验unsignedintsourceIP; //32位源IP地址unsignedintdestIP; //32位目标IP地址}IpHeader;Windows是小端模式,所以h_len变量在version前面;如果是UNIX系统version在h_len变量前面。ICMP是(InternetControlMessageProtocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。/******************ICMP头部定义******************/typedefstruct_icmphdr{BYTEi_type; //ICMP报文类型BYTEi_code; //该类型中的代码号,一种ICMP报文的类型号和该类型中的代码号共同决定。USHORTi_cksum; //校验和USHORTi_id; //当前进程PIDUSHORTi_seq; //序列号,序列号从0开始,每发送一次新的回显请求就加1.ULONGtimestamp; //时间戳}IcmpHeader;增加了timestamp变量存储时间戳,用于计算传输数据的时间。SOCKET库使用winsock2API编程,必须包含头文件winsock2.h(链接环境WS2_32.LIB),头文件winsock.h(WSOCK32.LIB)是为了兼容winsock1程序时使用的,另外mswsock.h(MSWSOCK.DLL)是微软的扩展类,用于开发高性能的winsock程序。WINDOWS环境下SOCKET基本函数(1)WSAStartup函数intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。例:假如一个程序要使用2.1版本的Socket,那么程序代码如下

wVersionRequested=MAKEWORD(2,1);

err=WSAStartup(wVersionRequested,&wsaData);(2)WSACleanup函数intWSACleanup(void);应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。(3)WSASocket函数

SOCKETWSAAPIWSASocket(intaf,inttype,intprotocol,LPPROTOCOL_INFOlpProtocolInfo,Groupg,intiFlags);创建一个与指定传送服务提供者捆绑的套接口,可选地创建和/或加入一个套接口组。此函数为socket()的扩展版本,其功能都是创建一个原始套接字。使用时需要包含winsock2.h头文件和链接wsock32.lib库。参数定义:af:地址族描述。目前仅支持AF_INET格式,亦即ARPAInternet地址格式。type:新套接口的类型描述。protocol:套接口使用的特定协议,如果调用者不愿指定协议则定为0。lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af,type,protocol)被忽略。g:套接口组的描述字。iFlags:套接口属性描述。(4)closesocket函数

intclosesocket(SOCKETs);

closesocket函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构,因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描述符表中的对应表项,并且把s对应的套接字数据结构的引用次数减1。

closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。setsockopt函数

intPASCALFARsetsockopt(SOCKETs,intlevel,intoptname,constcharFAR*optval,intoptlen);setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。参数定义:s:标识一个套接口的描述字。level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。optname:需设置的选项。optval:指针,指向存放选项值的缓冲区。optlen:optval缓冲区长度。sendto函数

intPASCALFARsendto(SOCKETs,constcharFAR*buf,intlen,intflags,conststructsockaddrFAR*to,inttolen);指向一指定目的地发送数据,sendto()适用于已连接的数据报或流式套接口发送数据。参数定义:s:一个标识套接口的描述字。buf:包含待发送数据的缓冲区。len:buf缓冲区中数据的长度。flags:调用方式标志位。to:(可选)指针,指向目的套接口的地址。tolen:to所指地址的长度。recvfrom函数

intPASCALFARrecvfrom(SOCKETs,charFAR*buf,intlen,intflags,structsockaddrFAR*from,intFAR*fromlen);本函数用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。

参数定义:s:标识一个已连接套接口的描述字。buf:接收数据缓冲区。len:缓冲区长度。flags:调用操作方式。from:(可选)指针,指向装有源地址的缓冲区。fromlen:(可选)指针,指向from缓冲区长度值。程序功能函数(1)FillICMPData函数voidFillICMPData(char*icmp_data,intdatasize);初始化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; //回显请求(Ping请求)icmp_hdr->i_code=0; //要求有IP回应icmp_hdr->i_id=(USHORT)GetCurrentProcessId(); //取得当前进程PIDicmp_hdr->i_cksum=0; //校验和icmp_hdr->i_seq=0; //序列号 datapart=icmp_data+sizeof(IcmpHeader); memset(datapart,0xff,datasize-sizeof(IcmpHeader));//填充无用数据 return;}Checksum函数USHORTchecksum(USHORT*buffer,intsize);计算校验和。USHORTchecksum(USHORT*buffer,intsize){unsignedlongcksum=0;while(size>1){cksum+=*buffer++;size-=sizeof(USHORT);}if(size){cksum+=*(UCHAR*)buffer;}cksum=(cksum>>16)+(cksum&0xffff);cksum+=(cksum>>16);return(USHORT)(~cksum);}DecodeICMPHeader函数voidDecodeICMPHeader(char*buf,intbytes,SOCKADDR_IN*from);解析并显示ICMP数据。获取数据:IpHeader*iphdr=NULL; //IP头部IcmpHeader*icmphdr=NULL; //ICMP头部unsignedshortiphdrlen; //IP头部长度DWORDtick; //时间戳staticinticmpcount=0; //ICMP回显应答计数iphdr=(IpHeader*)buf; //强制转换为IP头部iphdrlen=iphdr->h_len*4; //IP头部长度tick=GetTickCount(); //获取时间戳数据验证:if(bytes<iphdrlen+ICMP_MIN) //接收数据太小{printf("Toofewbytesfrom%s\r\n",inet_ntoa(from->sin_addr));}icmphdr=(IcmpHeader*)(buf+iphdrlen); //强制转换为ICMP头部if(icmphdr->i_type!=ICMP_ECHOREPLY) //非回显应答{ if(icmphdr->i_type==3&&icmphdr->i_code==1) puts("无法访问目标主机"); else printf("Nonechotype:%dcode:%drecvd.\r\n",icmphdr->i_type,icmphdr->i_code);return;}if(icmphdr->i_id!=(USHORT)GetCurrentProcessId())//非本程序的回应{printf("其他程序的回应报文!\t错误代码%d\n",WSAGetLastError());return;}Cleanup函数voidCleanup();释放相关资源。voidCleanup(){if(m_hSocket!=INVALID_SOCKET)closesocket(m_hSocket); //关闭套接字HeapFree(GetProcessHeap(),0,recvbuf); //释放堆栈空间HeapFree(GetProcessHeap(),0,icmp_data); //释放堆栈空间WSACleanup(); //释放socket占用的资源 return;}程序主体输入地址数据初始化定义并初始化相关变量。绑定并创建套接字调用WSAStartup(MAKEWORD(2,2),&wsaData),绑定2.2套接字库。调用WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);创建套接字。setsockopt(m_hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));setsockopt(m_hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));设置套接字超时选项。解析目标地址首先尝试转换为网络字节地址,如果不是合法IP地址,则用gethostbyname()函数将目标地址当做是主机名或者域名。创建ICMP数据分配堆空间并初始化,然后调用FillICMPData()函数初始化ICMP数据。发送接收ICMP调用sendto()函数发送ICMP数据包,调用recvfrom()函数接收目标的ICMP回显请求报文。然后调用DecodeICMPHeader()函数解析并输出ICMP数据内容。统计信息输出发送和接收的ICMP数据包数量,计算并显示丢包率。程序流程图开始开始定义及初始化各个全局变量判断WSAStartup函数是否调用成功输出调用失败否创建套接字以及设置socket接收超时,发送超时选项;是解析输入的参数设置PING参数创建及填充ICMP数据报文判断是否已发送nCount次Break;发送,接收以及解析数据包输出PIING结果是结束清除残余否网络构建本次实验使用虚拟机安装windows7系统,与实体主机构成一个小型局域网进行测试。实际主机IP:系统:windowsxp虚拟主机IP:01系统:windows7由于本程序可以测试网络主机丢包率,所用可以不用搭建局域网。设计结果及分析1,无丢失的情况 通过以上结果分析ping程序能正常工作并准确的测试出丢包率,达到了实验的预期设想和目的。设计并构建了一个局域网,通过在这个计算机网络环境中的实际操作,对现代计算机网络的基本功能和体系结构进一步了解。通过一个本实验的PING程序的设计和实现,理解了TCP/IP协议的工作机制和编程方法;掌握计算机网络应用层协议的基本实现技术。设计体会SOCKET_RAW允许对较低层次的协议直接访问,比如IP、ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAWSOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,可以应用原始套接字来操纵网络层和传输层应用。这次设计需要对IP头部和ICMP头部结构有一定的了解,通过本次设计我对SOCKET编程方法有了更深的了解,加强了自己对网络编程的运用,同时也锻炼了自己查找资料,整理资料的能力。致谢在此由衷地感谢我们的黄玉清老师.,老师严谨细致、一丝不苟的作风一直是我工作、学习中的榜样;老师循循善诱的教导和不拘一格的思路给予我无尽的启迪;这次课程设计的每个实验细节和每个数据,都离不开老师您的细心指导。而您开朗的个性和宽容的态度,帮助我能够很顺利的完成了这次课程设计。同时感谢对我帮助过的同学们,谢谢你们对我的帮助和支持,让我感受到同学的友谊。参考文献[1]WinSocket编程[2]Ping程序设计[3]winsocket基础教程[4]rawsocket介绍及编程附录:ping程序代码#pragmacomment(lib,"ws2_32.lib")#include<winsock2.h>#include<ws2tcpip.h>#include<stdio.h>#include<stdlib.h>#include<string.h>/******************IP头部定义******************/typedefstruct_iphdr{unsignedcharh_len:4; //头长度,占4bitunsignedcharversion:4; //IP版本,占4bitunsignedchartos; //服务类型unsignedshorttotal_len; //包的总长度unsignedshortident; //包标示身份unsignedshortfrag_and_flags; //标志unsignedcharttl; //包生命周期unsignedcharproto; //协议类型unsignedshortchecksum; //IP校验unsignedintsourceIP; //32位源IP地址unsignedintdestIP; //32位目标IP地址}IpHeader;#defineICMP_ECHO8 //ICMP类型EchoRequest——回显请求(Ping请求)#defineICMP_ECHOREPLY0 //ICMP类型EchoReply——回显应答(Ping应答)#defineICMP_MIN8 //最小8字节的包头部/******************ICMP头部定义******************/typedefstruct_icmphdr{BYTEi_type; //ICMP报文类型BYTEi_code; //该类型中的代码号,一种ICMP报文的类型号和该类型中的代码号共同决定。USHORTi_cksum; //校验和USHORTi_id; //当前进程PIDUSHORTi_seq; //序列号,序列号从0开始,每发送一次新的回显请求就加1.ULONGtimestamp; //时间戳}IcmpHeader;/********************参数设置********************/#defineDEF_PACKET_SIZE32 //默认包大小#defineMAX_PACKET4096 //最大ICMP包长度#defineMAX_IP_HDR_SIZE60 //最大IP头长度intdatasize=DEF_PACKET_SIZE; //数据大小char*icmp_data=NULL; //ICMP数据缓存char*recvbuf=NULL; //接收数据缓存SOCKETm_hSocket=INVALID_SOCKET; //套接字char*ipdest=NULL; //目标IP地址intsendNum; //发送的回显请求数intrecvNum; //接收的回显应答数/********************初始化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; //回显请求(Ping请求)icmp_hdr->i_code=0; //要求有IP回应icmp_hdr->i_id=(USHORT)GetCurrentProcessId(); //取得当前进程PIDicmp_hdr->i_cksum=0; //校验和icmp_hdr->i_seq=0; //序列号 datapart=icmp_data+sizeof(IcmpHeader); memset(datapart,0xff,datasize-sizeof(IcmpHeader));//填充无用数据 return;}/******************校验和******************/USHORTchecksum(USHORT*buffer,intsize){unsignedlongcksum=0;while(size>1){cksum+=*buffer++;size-=sizeof(USHORT);}if(size){cksum+=*(UCHAR*)buffer;}cksum=(cksum>>16)+(cksum&0xffff);cksum+=(cksum>>16);return(USHORT)(~cksum);}/***********************解析ICMP数据***********************/voidDecodeICMPHeader(char*buf,intbytes,SOCKADDR_IN*from){IpHeader*iphdr=NULL; //IP头部IcmpHeader*icmphdr=NULL; //ICMP头部unsignedshortiphdrlen; //IP头部长度DWORDtick; //时间戳staticinticmpcount=0; //ICMP回显应答计数iphdr=(IpHeader*)buf; //强制转换为IP头部iphdrlen=iphdr->h_len*4; //IP头部长度tick=GetTickCount(); //获取时间戳if(bytes<iphdrlen+ICMP_MIN) //接收数据太小{printf("Toofewbytesfrom%s\r\n",inet_ntoa(from->sin_addr));}icmphdr=(IcmpHeader*)(buf+iphdrlen); //强制转换为ICMP头部if(icmphdr->i_type!=ICMP_ECHOREPLY) //非回显应答{ if(icmphdr->i_type==3&&icmphdr->i_code==1) puts("无法访问目标主机"); else printf("Nonechotype:%dcode:%drecvd.\r\n",icmphdr->i_type,icmphdr->i_code);return;}if(icmphdr->i_id!=(USHORT)GetCurrentProcessId())//非本程序的回应{printf("其他程序的回应报文!\t错误代码%d\n",WSAGetLastError());return;}DWORDtick0;tick0=tick-icmphdr->timestamp; //获取响应时间if(tick0<1)printf("来自%s的回复:字节=%d时间<1msTTL=%dicmp_seq=%d\n",inet_ntoa(from->sin_addr),bytes-DEF_PACKET_SIZE,iphdr->ttl,icmphdr->i_seq);else printf("来自%s的回复:字节=%d时间=%dmsTTL=%dicmp_seq=%d\n",inet_ntoa(from->sin_addr),bytes-DEF_PACKET_SIZE,tick0,iphdr->ttl,icmphdr->i_seq);icmpcount++; recvNum++; //接收的回显应答数 return;}/********************释放资源********************/voidCleanup(){if(m_hSocket!=INVALID_SOCKET)closesocket(m_hSocket); //关闭套接字HeapFree(GetProcessHeap(),0,recvbuf); //释放堆栈空间HeapFree(GetProcessHeap(),0,icmp_data); //释放堆栈空间WSACleanup(); //释放socket占用的资源 return;}/********************主函数********************/intmain(intargc,char*argv[]){ charadd[105]; printf("ping\nEnterIP:"); scanf("%s",add); ipdest=add; unsignedintnCount=4; inttimeout=1000;/********************初始化********************/WSADATAwsaData; //保存WSAStartup返回的WindowsSockets初始化信息SOCKADDR_INm_addrDest; //目标地址SOCKADDR_INm_addrFrom; //接收地址sendNum=nCount; recvNum=0;USHORT seq_no=0;/********************绑定socket库********************/if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0){printf("Sorry,youcannotloadsocketdll!");}/**********************创建套接字**********************/m_hSocket=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);if(m_hSocket==INVALID_SOCKET){printf("socket创建失败!");}/********************设置套接字选项********************/intbread=setsockopt(m_hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));if(bread==SOCKET_ERROR){printf("设置socket接收超时选项错误!");}bread=setsockopt(m_hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));if(bread==SOCKET_ERROR){printf("设置socket发送超时选项错误!");}/********************目标地址初始化********************/memset(&m_addrDest,0,sizeof(m_addrDest));m_addrDest.sin_family=AF_INET; //地址族/*internetwork:UDP,TCP,etc.*/if((m_addrDest.sin_addr.s_addr=inet_addr(ipdest))==INADDR_NONE) //不是合法的IP地址{structhostent*hp=NULL;if((hp=gethostbyname(ipdest))!=NULL) //尝试解析主机名{memcpy(&(m_addrDest.sin_addr),hp->h_addr,hp->h_length);m_addrDest.sin_family=hp->h_addrtype;}else{printf("不能找到名为%s的主机\t错误代码%d\n",ipdest,WSAGetLastError());exit(0);}}printf("正在Ping%s具有%d字节的数据:\n\n",inet_ntoa(m_addrDest.sin_addr),dat

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论