1、4.1系统设计 34.2系统实现 45、设计总结 135.1 完成的工作及评价 135.2 遇到的问题及解决过程 135.3 心得体会及建议 146、使用说明 14参考文献 141、课程设计任务描述 另写一个程序,取代windows下的Ping程序命令,可以Ping指定主机、一批主机,并显示输出结果。2、设计原理及相关知识2.1设计原理ping命令的工作原理1 是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,通过返回的信息来判断网络的连接状况。要实现直接对IP和ICMP包进行操作,设计采用RAW模式的SOCKET编程,实现网络的连通性测试
2、,探测主机到主机之间是否可以通信,如果不能ping到某台主机,表明不能和这台主机建立连接。Ping程序是面向向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。2.2相关知识了解ping命令实现原理2 ,就要了解ping命令所使用到的TCP/IP协议。PING利用ICMP协议包来测试另一个主机是否可达。原理是用类型码为0的ICMP发送请求,收到请求主机则用类型码为8 的ICMP回应。Ping程序来计算时间间隔,并计算有多少个包被送达。用户就可以判断网络的大致情况。ICMP协议是IP层的 一个协议,但是由于差错报告在发送给报文源发方时可能也要经过若干子网,因此牵涉到路由选择等问题
3、,所以ICMP报文需通过IP协议来发送。ICMP数据 报的数据发送前需要两级封装:首先添加ICMP报头形成ICMP报文,再添加IP报头形成IP数据报。TCP/IP应用于传输层之上,TCP/IP应用程序需要调用传输层的接口才能实现应用程序之间的通讯。应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCPIP协议交互提供了称为套接字(Socket)的接口。套接字3 接口是对网络中不同主机之间应用进程双向通信端点的抽象
4、。提供了应用进程利用协议栈交换数据的机制。两个应用进程只要分别连接自己的套接字,就能方便通过计算机网络进行通信,不用去管网络的复杂结构,也不用管数据传送是复杂过程。3、需求分析3.1功能需求实现的 ping命令,能用于测试一个主机到另一个主机间的联通情况。程序能实现基本的ping操作,发送ICMP回显请求报文(可以更改发送的报文数目),接收显应答报文。显示发送数据包个数;接收数据包个数;丢失包个数,最大时间,最小时间以及平均时间。3.2性能需求 能真实的的反映两台主机的联通情况3.3界面需求界面需要显示明确,当联通失败时能让人一眼就看出问题所在。4系统设计及实现4.1系统设计创建通信的套接字-
5、将地址、端口信息与套接字绑定-构建IP包头与ICMP包头-发送构建的数据包-接收对方主机的回应-给出程序反馈信息系统执行的流程图如下图4.1所示:图4.14.2系统实现(1)模块或函数功能描述void ping(int argc,char *argv):ping()函数是本程序的核心部分,它通过调用其他模块的函数来实现,其主要步骤包括初始化winsock,初始化协议,创建套接字,名字解析。int pack(int pack_no):构建数据报void send_packet(void):发送数据报void recv_packet(void):接收数据报 int unpack(unsigned
6、char *buf,int len):剥去ICMP报头加显示unsigned short cal_checksum(unsigned short *buffer, int size); /求校验和函数void free():用于释放占用的资源,包括关闭套接字和释放winsock(2)关键的代码IP报头字段数据结构struct IP unsigned char ip_hl:4; /首部长度 unsigned char ip_ver: /IP版本号 unsigned char ip_tos; /服务类型 unsigned short ip_len; /总长度 unsigned short ip_i
7、d; /标识 unsigned short ip_off; /标志位 unsigned char ip_ttl; /生存时间 unsigned char ip_port; /协议类型(TCP、UDP等) unsigned short ip_checksum; /ip首部校验和 unsigned long ip_source; /源ip地址 unsigned long ip_dest; /目的ip地址 ;ICMP报头字段数据结构struct ICMP unsigned char icmp_type; / 消息类型 unsigned char icmp_code; / 代码 unsigned sh
8、ort icmp_checksum; / 校验和 unsigned short icmp_id; / 用来惟一标识此请求的ID号,通常设置为进程ID unsigned short icmp_seq; / 序列号 unsigned long icmp_data; / 时间戳Ping函数void ping(int argc,char *argv) WSADATA wsadata;/WSADATA数据结构 struct hostent *host; struct protoent *protocol; char *par_host; par_host=argv1; pid=getpid(); /获取
9、main的进程id,用于设置icmp的标志符 /使用Socket的程序在使用Socket之前必须调用WSAStartup函数完成对Winsock服务的初始化 /初始化winsock不成功 if(WSAStartup(0x1010,&wsadata)!=0) printf(wsastartup errorn); exit(1); /初始化协议 if( (protocol=getprotobyname(ICMP) )=NULL) getprotobyname errorn / printf(所选协议的协议名:%snn,protocol-p_name);以主机字节顺序排列的协议号为:%dnnp_pr
10、oto); /套接字创建不成功 if(sockfd=socket(AF_INET,SOCK_RAW,protocol-p_proto)0)socket errorn /设置套接字属性 if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)h_addr,host-h_length); /将获取到的IP值赋给目的地地址中的相应字段 if(host=gethostbyaddr(host-h_addr,4,PF_INET)/ 将ip解析为主机名 par_host=host-h_name; else/或者输出
11、不明的主机 if(dest_addr.sin_addr.s_addr=inet_addr(par_host)=INADDR_NONE) printf(Unknow host %sn,par_host); exit(1); printf(nPinging %s %s with %d bytes of data:nn,inet_ntoa(dest_addr.sin_addr),par_host,SEND_SIZE);void send_packet() int packetsize; static int pack_no=0; packetsize=pack(pack_no+); /sendpacket为要发送的内容,由pack()函数设定,dest_addr是目的地址 if( sendto(sockfd,(char *)sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr) ) success=unpack(recvpacket,n); else if (WSAGetLastError() = WSAETIMEDOUT) Request timed out.n return; while(!success);int pack(int pack_no ) int packsize;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1