ping程序实现
【实验目的】
熟悉原始套接字编程的基本流程
理解ping程序的实现机制
理解ICMP协议的基于作用和报文格式。
完成原始套接字的配置。
【实验要求】
- 构造ICMP协议首部结构
- 构造ICMP回射请求结构。
- 构造ICMP回射应答结构。
- 构造IP首部结构。
- 创建原始套接字。
- 根据用户指定的地址获取目标IP。
- 对目标地址循环发送ICMP请求。
- 等待对方响应,并计算时间间隔。
【实验过程】
- 程序的运行过程
将相关的数据结构的定义写在ping.h头文件中,并将其包含着源文件ping.c中。编译通过后,在命令窗口执行。根据用户输入的主机名称或ip地址,向对方发送ICMP请求报文,收到回复的ICMP应答报文后,计算时间差来显示与对方的连通情况。具体的运行结果如下图所示。
从图中可以看到,myping程序的输入参数是www.baidu.com。程序中调用gethostbyname()函数将主机名转换为ip地址61.135.185.32。并循环四次向该地址发送ICMP请求包,每次收到ICMP应答包后计算往返的时间间隔。数据包包括8个字节的ICMP协议头,32个字节包括ICMP协议的数据,其中协议头中包含时间字段。 - 数据抓包
使用使用wireshark软件,可以将程序运行过程中发送和接收到的数据包捕获到。
【实验代码】
- 头文件 ping.h
#pragma pack(1)
#define ICMP_ECHOREPLY 0
#define ICMP_ECHOREQ 8
// IP Header -- RFC 791
typedef struct tagIPHDR
{
u_char VIHL; // Version and IHL
u_char TOS; // Type Of Service
short TotLen; // Total Length
short ID; // Identification
short FlagOff; // Flags and Fragment Offset
u_char TTL; // Time To Live
u_char Protocol; // Protocol
u_short Checksum; // Checksum
struct in_addr iaSrc; // Internet Address - Source
struct in_addr iaDst; // Internet Address - Destination
}IPHDR, * PIPHDR;
// ICMP Header - RFC 792
typedef struct tagICMPHDR
{
u_char Type; // Type
u_char Code; // Code
u_short Checksum; // Checksum
u_short ID; // Identification
u_short Seq; // Sequence
char Data; // Data
}ICMPHDR, * PICMPHDR;
#define REQ_DATASIZE 32 // Echo Request Data size
// ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, * PECHOREQUEST;
// ICMP Echo Reply
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char cFiller[256];
}ECHOREPLY, * PECHOREPLY;
#pragma pack()
#pragma once
- 源程序ping.cpp
// PING.C -- Ping program using ICMP and RAW Sockets
//
#define _WINSOCK_DEPRECATED_NO_WARNINGS
//#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
//#include <winsock.h>
#include <WinSock2.h>
#pragma comment (lib,"Ws2_32.lib")
#include "ping.h"
// Internal Functions
void Ping(LPCSTR pstrHost);
void ReportError(LPCSTR pstrFrom);
int WaitForEchoReply