一、实现原理
ping利用ICMP协议包来侦测另一个主机是否可达。Ping的原理是使用了类型码为8的ICMP回送请求包,收到请求的主机则用类型码为0的ICMP回应报文。如果应答包和请求包的标示号、序号和内容相同的话,则证明能够ping通,网络设备可用。ping程序计算间隔时间,并计算有多少个包被送达,用户就可以判断网络大致的情况。
系统提供的Ping还列出来了传送的时间和TTL等数据,命令提供了多种参数。下面的程序用ICMP协议实现了简单的Ping功能。由于用的是ICMP协议,因此,我们不能够通过建立一个SOCK_STREAM或SOCK_DGRAM来发送这个包,只能够使用SOCK_RAW来自己构造数据包。
二、ping程序的工作流程
三、主要函数和数据结构
//定义IP头部
typedef struct iphdr {
unsigned int h_len:4; // 头部长
unsigned int version:4; // 版本号
unsigned char tos; // 服务类型
unsigned short total_len; // 总长度
unsigned short ident; // 标识
unsigned short frag_and_flags; //标志
unsigned char ttl; //生存时间
unsigned char proto; // 上层协议
unsigned short checksum; // 校验和
unsigned int sourceIP; //源IP
unsigned int destIP; //目的IP
unsigned long
RoundTripTime; // RTT in milliseconds
}IpHeader;
// 定义ICMP 头部
typedef struct icmphdr {
BYTE i_type; //类型
BYTE i_code; //代码
USHORT i_cksum; //校验和
USHORT i_id; //标识
USHORT i_seq; //序列号
ULONG timestamp; //数据
}IcmpHeader;
#define STATUS_FAILED 0xFFFF
#define DEF_PACKET_SIZE
32
//默认数据包长度
#define DEF_PACKET_NUMBER 4
//默认发送ICMP请求的次数
#define MAX_PACKET 1024
//数据包最大长度
#define xmalloc(s)
HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
//分配内存
#define xfree(p) HeapFree (GetProcessHeap(),0,(p))
//释放内存
//填充icmp数据包
void fill_icmp_data(char *, int);
//计算校验和
USHORT checksum(USHORT *, int);
//收到数据后解码
int decode_resp(char *,int ,struct sockaddr_in
*);
//计算接收耗费的时间的最小,最大和平均值
void PX(int *input, int inputlen, int
*output);
四、ping程序的具体实现
#define ICMP_ECHO 8 //ICMP回显请求
#define ICMP_ECHOREPLY 0 //ICMP回显应答
#define ICMP_MIN 8 //ICMP数据包最短为8个字节
//定义IP头部
typedef struct iphdr {
unsigned int h_len:4; // 头部长
unsigned int version:4; // 版本号
unsigned char tos; // 服务类型
unsigned short total_len; // 总长度
unsigned short ident; // 标识
unsigned short frag_and_flags; //标志
unsigned char ttl; //生存时间
unsigned char proto; // 上层协议
unsigned short checksum; // 校验和
unsigned int sourceIP; //源IP
unsigned int destIP; //目的IP
unsigned long
RoundTripTime; // RTT in milliseconds
}IpHeader;
// 定义ICMP 头部
typedef struct icmphdr {