Ping程序设计c语言课程设计Word文档格式.docx

上传人:b****1 文档编号:812427 上传时间:2023-04-29 格式:DOCX 页数:26 大小:23.60KB
下载 相关 举报
Ping程序设计c语言课程设计Word文档格式.docx_第1页
第1页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第2页
第2页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第3页
第3页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第4页
第4页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第5页
第5页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第6页
第6页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第7页
第7页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第8页
第8页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第9页
第9页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第10页
第10页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第11页
第11页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第12页
第12页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第13页
第13页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第14页
第14页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第15页
第15页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第16页
第16页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第17页
第17页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第18页
第18页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第19页
第19页 / 共26页
Ping程序设计c语言课程设计Word文档格式.docx_第20页
第20页 / 共26页
亲,该文档总共26页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Ping程序设计c语言课程设计Word文档格式.docx

《Ping程序设计c语言课程设计Word文档格式.docx》由会员分享,可在线阅读,更多相关《Ping程序设计c语言课程设计Word文档格式.docx(26页珍藏版)》请在冰点文库上搜索。

Ping程序设计c语言课程设计Word文档格式.docx

(1)初始化模块。

改模块用于初始化各个全局变量,为全局变量赋初始值;

初始化,加载库。

(2)功能控制模块。

改模块是被其它模块调用,其功能包括获取参数、计算校验和填充数据报文、释放占用资源和显示用户帮助。

(3)数据报解读模块。

改模块用于解读接收到的报文和选项。

(4)测试模块。

改模块是本程序的核心模块,调用其他模块实现其功能,主要是实现的功能。

2.系统流程图

系统执行的流程图9.2所示。

程序首先调用IniPing()函数初始化各全局变量,然后GetArgments()函数获取用户输入的参数,检查用户输入的参数,如果参数不正确或者没有输入参数,则显示用户帮助信息(Userhelp),并结束程序;

如果参数正确,则对指定目的地执行Ping命令,如果Ping通,则显示Ping结果并释放占用资源,如果没有Ping通,则报告错误信息,并释放占用资源。

显示帮助信息

图9.2系统流程图

3.参数获取(GetArgments()函数)流程图

获取的参数包括“-r”(记录路由)、“-n”(记录条数程序,任意的整数)和datasize(数据报大小)。

程序首先判断每一个参数的第一字符,如果第一个字符是“-”(短横线),则认为是“-r”或者“-n”中的一个,然后作进一步判断。

如果该参数的第二个字符是数字,则判断该参数为记录的条数,如果该参数的第二个字符是“r”,则判断该参数为“-r”,用于记录路由;

如果参数的第一个字符是数字,则认为参数是IP地址;

或者datasize,然后作进一步的判断。

如果该参数中不存在非数字的字符,则判断该参数为datasize;

如果存在非数字的字符,则判断该参数为IP地址;

其他情况则判断为主机名。

参数获取的流程如图9.3所示。

记录到变量

Lpdest中

图9.3参数获取流程图

4.ping()函数流程图

ping()函数是本程序的核心部分它调用其他模块的函数来实现,其主要步骤包括创建接字,设置路由选项(如果需要的话)、设置接收和发送超时值、名字解析(如果需要的话)、分配内存、创建ICMP报文、发送ICMP请求报文、接收ICMP应答报文和解读ICMP报文。

其执行流程如图9.4所示。

输出失败信息

记录数达到指定值?

图9.4Ping函数流程图

9.3.2数据结构设计

本程序定义了3个结构体:

-iphdr、-icmphdr、和-ipotionhdr,分别用于存放IP报头信息、ICMP报头信息和IP路由选项信息。

1.定义IP报头结构体

Typedefstruct_iphdr

{

Unsignedinth_len:

4;

Unsignedintversion:

Unsignedchartos;

Unsignedshorttotal_len;

Unsignedshortident;

Unsignedshortfrag_flags;

Unsignedcharttl;

Unsignedchorproto;

Unsignedshortchecksum;

UnsignedintsourceIP;

UnsignedintdestIP;

}IpHeader;

其中各字段表示意义如下。

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];

其中各字段表示意义如下。

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"

/*加载头文件*/

#include<

winsock2.h>

ws2tcpip.h>

stdio.h>

stdlib.h>

math.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();

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(inttimeout);

/*IP报头字段数据结构*/

typedefstruct_iphdr

unsignedinth_len:

/*IP报头长度*/

unsignedintversion:

/*IP的版本号*/

unsignedchartos;

/*服务的类型*/

unsignedshorttotal_len;

/*数据报总长度*/

unsignedshortident;

/*惟一的标识符*/

unsignedshortfrag_flags;

/*分段标志*/

unsignedcharttl;

/*生存期*/

unsignedcharproto;

/*协议类型(TCP、UDP等)*/

unsignedshortchecksum;

/*校验和*/

unsignedintsourceIP;

/*源IP地址*/

unsignedintdestIP;

/*目的IP地址*/

/*ICMP报头字段数据结构*/

typedefstruct_icmphdr

/*ICMP报文类型*/

BYTEi_code;

/*该类型中的代码号*/

/*校验和*/

/*序列号*/

/*时间戳*/

/*IP选项头字段数据结构*/

typedefstruct_ipoptionhdr

unsignedcharcode;

/*选项类型*/

unsignedcharlen;

/*选项头长度*/

unsignedcharptr;

/*地址偏移长度*/

unsignedlongaddr[9];

/*记录的IP地址列表*/

}IpOptionHeader;

/*定义全局变量*/

SOCKETm_socket;

IpOptionHeaderIpOption;

SOCKADDR_INDestAddr;

SOCKADDR_INSourceAddr;

char*icmp_data;

char*recvbuf;

USHORTseq_no;

char*lpdest;

intdatasize;

BOOLRecordFlag;

doublePacketNum;

BOOLSucessFlag;

2.初始化模块

/*初始化变量函数*/

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:

%d\n"

GetLastError());

return;

}

m_socket=INVALID_SOCKET;

}

3.功能控制模块

/*显示信息函数*/

voidUserHelp()

UserHelp:

ping-r<

host>

[datasize]\n"

);

-rrecordroute\n"

-nrecordamount\n"

hostremotemachinetoping\n"

datasizecanbeupto1KB\n"

ExitProcess(-1);

/*获取ping选项函数*/

voidGetArgments(intargc,char**argv)

inti;

intj;

intexp;

intlen;

intm;

/*如果没有指定目的地地址和任何选项*/

if(argc==1)

\nPleasespecifythedestinationIPaddressandthepingoptionasfollow!

\n"

UserHelp();

for(i=1;

i<

argc;

i++)

len=strlen(argv[i]);

if(argv[i][0]=='

-'

/*选项指示要获取记录的条数*/

if(isdigit(argv[i][1]))

{

PacketNum=0;

for(j=len-1,exp=0;

j>

=1;

j--,exp++)

/*根据argv[i][j]中的ASCII值计算要获取的记录条数(十进制数)*/

PacketNum+=((double)(argv[i][j]-48))*pow(10,exp);

}

else

switch(tolower(argv[i][1]))

/*选项指示要获取路由信息*/

case'

r'

:

RecordFlag=TRUE;

break;

/*没有按要求提供选项*/

default:

UserHelp();

/*参数是数据报大小或者IP地址*/

elseif(isdigit(argv[i][0]))

{

for(m=1;

m<

len;

m++)

if(!

(isdigit(argv[i][m])))

/*是IP地址*/

lpdest=argv[i];

break;

/*是数据报大小*/

elseif(m==len-1)

datasize=atoi(argv[i]);

}

/*参数是主机名*/

else

/*求校验和函数*/

USHORTCheckSum(USHORT*buffer,intsize)

unsignedlongcksum=0;

while(size>

1)

cksum+=*buffer++;

size-=sizeof(USHORT);

if(size)

cksum+=*(UCHAR*)buffer;

/*对每个16bit进行二进制反码求和*/

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;

i_code=0;

/*获取当前进程IP作为标识符*/

i_id=(USHORT)GetCurrentProcessId();

i_cksum=0;

i_seq=0;

datapart=icmp_data+sizeof(IcmpHeader);

/*以数字0填充剩余空间*/

memset(datapart,'

0'

datasize-sizeof(IcmpHeader));

/*释放资源函数*/

voidFreeRes()

/*关闭创建的套接字*/

if(m_socket!

=INVALID_SOCKET)

closesocket(m_socket);

/*释放分配的内存*/

HeapFree(GetProcessHeap(),0,recvbuf);

HeapFree(GetProcessHeap(),0,icmp_data);

/*注销WSAStartup()调用*/

WSACleanup();

4.数据报解读模块

/*解读IP选项头函数*/

voidDecodeIPOptions(char*buf,intbytes)

IpOptionHeader*ipopt=NULL;

IN_ADDRinaddr;

HOSTENT*host=NULL;

/*获取路由信息的地址入口*/

ipopt=(IpOptionHeader*)(buf+20);

RR:

"

for(i=0;

(ipopt->

ptr/4)-1;

inaddr.S_un.S_addr=ipopt->

addr[i];

if(i!

/*根据IP地址获取主机名*/

host=gethostbyaddr((char*)&

inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET);

/*如果获取到了主机名,则输出主机名*/

if(host)

(%-15s)%s\n"

inet_ntoa(inaddr),host->

h_name);

/*否则输出IP地址*/

(%-15s)\n"

inet_ntoa(inaddr));

return;

/*解读ICMP报头函数*/

voidDecodeICMPHeader(c

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2