《编程模拟ping程序》由会员分享,可在线阅读,更多相关《编程模拟ping程序(18页珍藏版)》请在金锄头文库上搜索。
1、一、实验题目编程模拟ping程序,实现Ping程序的基本功能,即接收到一个ping程序数据包后给 出回应。二、原理概述ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。ping命 令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文, 它将把报文一模一样地传回给发送者,这有点象潜水艇声纳系统中使用的发声装置。想要了 解ping命令的原理必须了解ICMP协议、ICMP报文格式和IP报文格式。(1)ICMP报文结构ICMP报文结构:ICMP报文前四个字节为报文头部分,第一个字节为报文类型,第二个字 节未用,第三四个字节为报文的校验和。从第四个字节开
2、始为长度可变的数据段,该段的内 容取决于ICMP的类型,本文所要使用的请求报文和请求应答报文的数据段中前四个字节是 报文的标识符和顺序号。对于整个ICMP报文来说其长度最长不能超过64K字节。ICMP报文 结构如图1所示。07 815 1631 3247 4863 64类型未用校验和标识符顺序号数据(2)IP报文结构ICMP报文和其它位于IP层的报文一样是作为IP报文的数据段加上IP报文头组成IP 数据报发出,其中IP报文头长度一般为20个字节。如图2所示。IP报文头ICMP报文(数据段)三、设计方案根据实验题目查找相关资料,熟悉及理解ping的工作原理,从而进一步设计ping程序 的功能图和
3、系统流程图。准备工作做好后就可上机调试,验证其可行性并查找漏洞,完善 ping程序。(1)ping程序的设计包含了 4部分:IP、ICMP的头结构,主函数模块,CMP数据包校验 和的计算和使用说明模块。Ping程序设计IP、ICM使ICM主P数用P的函据说头数包明结模校模构块验块和(2)系统流程图首先在主函数里定义变量同时进行初始化,然后检查参数的正确性,如果参数不正确或 者没有输入参数,则显示用户帮助信息(Usage),并结束程序;如果参数正确,则对指定目 的地执行Ping命令,如果Ping通,则显示Ping结果并释放占用资源,如果没有Ping通, 则报告错误信息,并释放占用资源。如图3所示
4、。图3 系统流程图(3)数据结构设计本程序定义了 2个结构体:iphdr、-ihdr,分别用于存放IP报头信息、ICM P报头信息。(4)主函数,使用说明,数据包校验和的计算的相关程序在程序中会有体现。四、程序编写#include /Winsock API 头文件#include #include #pragma comment(lib,ws2_32.lib) /Winsock API 连接库文件/*IP头结构*/typedef struct iphdrBYTE h_len:4;/首部长度指的是IP层头部占32 bit字的数目/(也就是IP层头部包含多少个4字节,实际字节数4*hlen),BY
5、TE version:4; /IP 版本号BYTE tos;/服务类型 TOSUSHORT total_len; /IP 包总长度USHORT ident; /标识USHORT frag_and_flags; /标志位BYTE ttl;/生存时间BYTE proto;/协议USHORT checksum; /IP 首部校验和UINT sourceIP; /源 IP 地址(32 位)UINT destIP; /目的 IP 地址(32 位)IpHeader;/*ICMP头结构*/typedef struct _ihdrBYTE i_type; /类型 发出的 ICMP 为 8(ICMP_ECHO_
6、REQUEST),接受到的 ICMP 为 0BYTE i_code; /代码USHORT i_cksum; /ICMP 包校验和USHORT i_id;/识别号(一般用进程号作为标识号)USHORT i_seq;/报文序列号(一般设置为0)ULONG times tamp;/时间戳IcmpHeader;USHORT checksum(USHORT *,int); /函数声明:计算 ICMP 包校验和void usage();/函数声明:使用帮助void main(int argc,char *argv)char *ICMP_DEST_IP;/ 目标主机 IPWSADATA wsaData;st
7、ruct sockaddr_in dest, from;/地址结构int datasize; /ICMP 报文大小int ret ;/API函数 返回值int i;/循环计数器int attachsize=32;/ICMP数据包附加字节数,本程序默认为32字节int n=4;/发送数据包个数,本程序默认发送4个ICMP数据包int ti meo ut;/延迟DWORD packe trecv=0;/收到的数据包DWORD min time=0;/用时最短时间DWORD max time=0;/用时最长时间DWORD average time=0;/平均用时DWORD los tpercen t
8、二 0;/丢包率DWORD st ar t; /发送ICMP包起始时间char *icmp_data;/ICMP 包char *recvbuf;/ICMP应答接收缓冲区int fromlen二sizeof(from);/地址结构体的大小SOCKET sockRaw;/原始套接字char *attachdata;/ICMP 包附加数据PHOSTENT hos tinfo;/主机信息(域名-IP)/读取命令行参数if(1=argc)/如果仅有一个默认的命令行参数则显示程序说明/默认的第一个命令行参数为本程序的路径usage();re turn;/退出程序else /如果有多个命令行参数for(i=
9、1;ih_addr_list);sockRaw二socke t( AF_INET,/协议族(AF_INET: TCP_IP)S0CK_RAW,/套接字类型(原始套接字) IPPR0T0_ICMP/协议类型(ICMP 协议);/创建原始套接字开始if(INVALID_SOCKET=sockRaw)/socket 调用失败返回 INVALID_SOCKET,反之返回套接字 句柄prin tf(创建原始套接字出错!n);WSACleanupO; /中止 Windows Sockets DLL 的使用,释放资源re turn;/退出程序/设置目的IP memset(&dest,0,sizeof(des
10、t);addr=inet_addr(ICMP_DEST_IP);dest.sin_family=AF_INET;attachdata=(char*)malloc(attachsize);memset(attachdata,0,attachsize);/ICMP 包数据部分 填充 attachsize 字节 0 datasize二sizeof(IcmpHeader)+attachsize;/ICMP 数据包总大小(头+体) icmp_data=(char*)malloc(datasize);/根据上面计算的结果为ICMP包数据分配内存 recvbuf=(char*)malloc(200);/me
11、mset(icmp_data,0,datasize);/ICMP数据包封装(IcmpHeader *)icmp_data)-i_type=8;word 专业资料-可复制编辑-欢迎下载(IcmpHeader *)icmp_data)-i_code=0;(IcmpHeader *)icmp_data)-i_id=(USHORT)GetCurrentProcessId();(IcmpHeader *)icmp_data)-timestamp=GetTickCount();(IcmpHeader *)icmp_data)-i_seq=0; memcpy(icmp_data+sizeof(IcmpHea
12、der),attachdata,attachsize);/ICMP 包数据部分 填充32字节0(IcmpHeader *)icmp_data)-i_cksum=0;/计算ICMP包校验和(IcmpHeader *)icmp_data)-i_cksum=checksum(USHORT *)icmp_data,datasize); timeout=1000;/设置发送延迟setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout); timeout=2000;/设置接受延迟setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout); printf(Pinging %s with %d bytes of data:nn,ICMP_DEST_IP,attachsize); for(