这是一个老话题了,但是我刚学会...

 

我们的目的是实现这么个东西:

C++实现Ping

之所以用红框框一下是因为,从baidu.com到123.125.114.144的过程是DNS解析,我们暂时先实现ping的部分。

 

基础知识

ping的过程是向目的IP发送一个type=8的ICMP响应请求报文,目标主机收到这个报文之后,会向源IP(发送方,我)回复一个type=0的ICMP响应应答报文。

那上面的字节、往访时间、TTL之类的信息又是从哪来的呢?这取决于IP和ICMP的头部。

 

IP头部:

C++实现Ping

头部内容有点多,我们关心的只有以下几个:

IHL:首部长度。因为IP的头部不是定长的,所以需要这个信息进行IP包的解析,从而找到Data字段的起始点。

    另外注意这个IHL是以4个字节为单位的,所以首部实际长度是IHL*4字节。

Time to Live:生存时间,这个就是TTL了。

Data:这部分是IP包的数据,也就是ICMP的报文内容。

 

ICMP响应请求/应答报文头部:

C++实现Ping

Type:类型,type=8表示响应请求报文,type=0表示响应应答报文。

Code:代码,与type组合,表示具体的信息,参考这里

Checksum:检验和,这个是整个ICMP报文的检验和,包括Type、Code、...、Data。

Identifier:标识符,这个一般填入本进程的标识符。

Sequence Number:序号

Data:数据部分

上面是标准的ICMP报文,一般而言,统计ping的往返时间的做法是,在ICMP报文的Data区域写入4个字节的时间戳。

在收到应答报文时,取出这个时间戳与当前的时间对比即可。

 

代码实现

 1 #pragma once
 2 
 3 #include <windows.h>
 4 
 5 //这里需要导入库 Ws2_32.lib,在不同的IDE下可能不太一样 
 6 //#pragma comment(lib, "Ws2_32.lib")
 7 
 8 #define DEF_PACKET_SIZE 32
 9 #define ECHO_REQUEST 8
10 #define ECHO_REPLY 0
11 
12 struct IPHeader
13 {
14     BYTE m_byVerHLen; //4位版本+4位首部长度
15     BYTE m_byTOS; //服务类型
16     USHORT m_usTotalLen; //总长度
17     USHORT m_usID; //标识
18     USHORT m_usFlagFragOffset; //3位标志+13位片偏移
19     BYTE m_byTTL; //TTL
20     BYTE m_byProtocol; //协议
21     USHORT m_usHChecksum; //首部检验和
22     ULONG m_ulSrcIP; //源IP地址
23     ULONG m_ulDestIP; //目的IP地址
24 };
25 
26 struct ICMPHeader
27 { 
28     BYTE m_byType; //类型
29     BYTE m_byCode; //代码
30     USHORT m_usChecksum; //检验和 
31     USHORT m_usID; //标识符
32     USHORT m_usSeq; //序号
33     ULONG m_ulTimeStamp; //时间戳(非标准ICMP头部)
34 };
35 
36 struct PingReply
37 {
38     USHORT m_usSeq;
39     DWORD m_dwRoundTripTime;
40     DWORD m_dwBytes;
41     DWORD m_dwTTL;
42 };
43 
44 class CPing
45 {
46 public:
47     CPing();
48     ~CPing();
49     BOOL Ping(DWORD dwDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);
50     BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);
51 private:
52     BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout);
53     USHORT CalCheckSum(USHORT *pBuffer, int nSize);
54     ULONG GetTickCountCalibrate();
55 private:
56     SOCKET m_sockRaw; 
57     WSAEVENT m_event;
58     USHORT m_usCurrentProcID;
59     char *m_szICMPData;
60     BOOL m_bIsInitSucc;
61 private:
62     static USHORT s_usPacketSeq;
63 };
View Code [ping.h]

相关文章:

  • 2021-05-30
  • 2022-01-29
  • 2021-07-21
  • 2022-01-31
  • 2021-07-17
  • 2021-10-29
猜你喜欢
  • 2022-02-10
  • 2022-12-23
  • 2021-09-19
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案