Ping C ++ implementation and ping implementation

Source: Internet
Author: User
Tags filetime

Ping C ++ implementation and ping implementation

This is an old topic, but I just learned...

 

Our goal is to achieve this thing:

The reason for using the red box is that the process from baidu.com to 123.125.114.144 is DNS resolution, and we will implement ping for the moment.

 

Basic knowledge

The ping process is to send an ICMP Response Request Packet of type = 8 to the destination IP address. After receiving the packet, the target host will send it to the source IP address (sender, I) returns an ICMP response message with type = 0.

Where did the above bytes, access time, TTL and other information come from? This depends on the IP address and ICMP header.

 

IP header:

There are a lot of headers, and we only care about the following:

IHL: header length. Because the IP header is not fixed, you need to parse the IP packet to find the starting point of the Data field.

Time to Live: TTL.

Data: This part is the IP packet Data, that is, the ICMP packet content.

 

ICMP Response Request/response packet header:

Type: type. type = 8 indicates the Response Message. Type = 0 indicates the Response Message.

Code: Code, combined with type, indicates the specific information, refer to here.

Checksum: check. This is the test of the entire ICMP packet, including Type, Code,..., and Data.

Identifier: Identifier. This is generally the Identifier of the current process.

Sequence Number: serial Number

Data: Data Section

The above is a standard ICMP message. Generally, the round-trip time of ping is counted by writing a four-byte timestamp in the Data area of the ICMP message.

When receiving the response message, retrieve the timestamp and compare it with the current time.

 

Code Implementation

1 # pragma once 2 3 # include <windows. h> 4 5 // here Ws2_32.lib needs to be imported into the database, which may be different in different ides. 6 // # pragma comment (lib, "Ws2_32.lib ") 7 8 # define DEF_PACKET_SIZE 32 9 # define ECHO_REQUEST 810 # define ECHO_REPLY 011 12 struct IPHeader13 {14 BYTE m_byVerHLen; // 4-bit version + 4-bit header length 15 BYTE m_byTOS; // service type 16 USHORT m_usTotalLen; // total length 17 USHORT m_usID; // ID 18 USHORT m_usFlagFragOffset; // 3-Bit Flag + 13-bit offset 19 BYTE m_byTTL; // TTL20 BYT E m_byProtocol; // Protocol 21 USHORT m_usHChecksum; // header check and 22 ULONG m_ulSrcIP; // source IP address 23 ULONG m_ulDestIP; // destination IP address 24 }; 25 26 struct ICMPHeader27 {28 BYTE m_byType; // type 29 BYTE m_byCode; // code 30 USHORT m_usChecksum; // test and 31 USHORT m_usID; // identifier 32 USHORT m_usSeq; // No. 33 ULONG m_ulTimeStamp; // Time Stamp (non-standard ICMP header) 34}; 35 36 struct PingReply37 {38 USHORT m_usSeq; 39 DWORD m_dwRoundTripTime; 40 DWORD m_dwBytes; 41 D WORD m_dwTTL; 42}; 43 44 class CPing45 {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 sequence (); 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_usacketseq; 63 };View Code [ping. h] 1 # include "ping. h "2 3 USHORT CPing: s_usPacketSeq = 0; 4 5 CPing: CPing (): 6 m_szICMPData (NULL), 7 m_bIsInitSucc (FALSE) 8 {9 WSADATA WSAData; 10 WSAStartup (MAKEWORD (1, 1), & WSAData); 11 12 m_event = WSACreateEvent (); 13 m_usCurrentProcID = (USHORT) GetCurrentProcessId (); 14 15 if (m_sockRaw = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0 ))! = SOCKET_ERROR) 16 {17 WSAEventSelect (m_sockRaw, m_event, FD_READ); 18 m_bIsInitSucc = TRUE; 19 20 m_szICMPData = (char *) malloc (DEF_PACKET_SIZE + sizeof (ICMPHeader )); 21 22 if (m_szICMPData = NULL) 23 {24 m_bIsInitSucc = FALSE; 25} 26} 27} 28 29 CPing ::~ CPing () 30 {31 WSACleanup (); 32 33 if (NULL! = M_szICMPData) 34 {35 free (m_szICMPData); 36 m_szICMPData = NULL; 37} 38} 39 40 BOOL CPing: Ping (DWORD dwDestIP, PingReply * pPingReply, DWORD dwTimeout) 41 {42 return PingCore (dwDestIP, pPingReply, dwTimeout); 43} 44 45 BOOL CPing: Ping (char * szDestIP, PingReply * pPingReply, DWORD dwTimeout) 46 {47 if (NULL! = SzDestIP) 48 {49 return PingCore (inet_addr (szDestIP), pPingReply, dwTimeout); 50} 51 return FALSE; 52} 53 54 BOOL CPing: PingCore (DWORD dwDestIP, pingReply * pPingReply, DWORD dwTimeout) 55 {56 // determine whether Initialization is successful 57 if (! M_bIsInitSucc) 58 {59 return FALSE; 60} 61 62 // configure SOCKET 63 sockaddr_in sockaddrDest; 64 sockaddrDest. sin_family = AF_INET; 65 sockaddrDest. protocol = dwDestIP; 66 int protocol = sizeof (sockaddrDest); 67 68 // construct ICMP packet 69 int nICMPDataSize = DEF_PACKET_SIZE + sizeof (ICMPHeader); 70 ULONG ulSendTimestamp = Queue (); 71 USHORT usSeq = ++ s_usacketseq; 72 memset (m_szICMP Data, 0, nICMPDataSize); 73 ICMPHeader * pICMPHeader = (ICMPHeader *) m_szICMPData; 74 pICMPHeader-> m_byType = ECHO_REQUEST; 75 pICMPHeader-> m_byCode = 0; 76 protocol-> m_usID = protocol; 77 pICMPHeader-> m_usSeq = usSeq; 78 pICMPHeader-> m_ulTimeStamp = ulSendTimestamp; 79 protocol-> m_usChecksum = CalCheckSum (USHORT *) m_szICMPData, nICMPDataSize); 80 81 // send ICMP packet 82 if (sendto (m_sockRaw, M_szICMPData, nICMPDataSize, 0, (struct sockaddr *) & sockaddrDest, nSockaddrDestSize) = SOCKET_ERROR) 83 {84 return FALSE; 85} 86 87 // determine whether to receive the corresponding message 88 if (pPingReply = NULL) 89 {90 return TRUE; 91} 92 93 char recvbuf [256] = {"\ 0"}; 94 while (TRUE) 95 {96 // receive Response Message 97 if (WSAWaitForMultipleEvents (1, & m_event, FALSE, 100, FALSE )! = WSA_WAIT_TIMEOUT) 98 {99 WSANETWORKEVENTS netEvent; 100 WSAEnumNetworkEvents (m_sockRaw, m_event, & netEvent); 101 102 if (netEvent. lNetworkEvents & FD_READ) 103 {104 ULONG nRecvTimestamp = hour (); 105 int nPacketSize = recvfrom (m_sockRaw, recvbuf, 256, 0, (struct sockaddr *) & sockaddrDest, & release ); 106 if (nPacketSize! = SOCKET_ERROR) 107 {108 IPHeader * pIPHeader = (IPHeader *) recvbuf; 109 USHORT usIPHeaderLen = (USHORT) (pIPHeader-> m_byVerHLen & 0x0f) * 4 ); 110 ICMPHeader * pICMPHeader = (ICMPHeader *) (recvbuf + usIPHeaderLen ); 111 112 if (pICMPHeader-> m_usID = m_usCurrentProcID // 113 of the packets sent by the current process & pICMPHeader-> m_byType = ECHO_REPLY // ICMP Response Message 114 & pICMPHeader-> m_usSeq = usSeq // 115 is the response packet of this request message) 116 {117 pPingReply -> M_usSeq = usSeq; 118 pPingReply-> m_dwRoundTripTime = audio-pICMPHeader-> m_ulTimeStamp; 119 pPingReply-> m_dwBytes = nPacketSize-extract-sizeof (ICMPHeader ); 120 pPingReply-> m_dwTTL = pIPHeader-> m_byTTL; 121 return TRUE; 122} 123} 124} 125 // timeout 126 if (GetTickCountCalibrate ()-ulSendTimestamp> = dwTimeout) 128 {129 return FALSE; 130} 131} 132 133 134 USHORT CPing: CalCheckSum (US HORT * pBuffer, int nSize) 135 {136 unsigned long ulCheckSum = 0; 137 while (nSize> 1) 138 {139 ulCheckSum + = * pBuffer ++; 140 nSize-= sizeof (USHORT); 141} 142 if (nSize) 143 {144 ulCheckSum + = * (UCHAR *) pBuffer; 145} 146 147 ulCheckSum = (ulCheckSum> 16) + (ulCheckSum & 0 xffff); 148 ulCheckSum + = (ulCheckSum> 16); 149 150 return (USHORT )(~ UlCheckSum); 151} 152 ULONG CPing: GetTickCountCalibrate () 153 {154 static ULONG s_ulFirstCallTick = 0; 155 static LONGLONG s_ullFirstCallTickMS = 0; 156 157 SYSTEMTIME systemtime; 158 FILETIME filetime; 160 GetLocalTime (& systemtime); 161 SystemTimeToFileTime (& systemtime, & filetime); 162 LARGE_INTEGER liCurrentTime; 163 liCurrentTime. highPart = filetime. dwHighDateTime; 164 liCurrentTime. lowPart = filetime. dwLowDateTime; 165 LONGLONG llCurrentTimeMS = liCurrentTime. quadPart/10000; 166 167 if (s_ulFirstCallTick = 0) 168 {169 s_ulFirstCallTick = GetTickCount (); 170} 171 if (s_ullFirstCallTickMS = 0) 172 {173 partition = llCurrentTimeMS; 174} 175 176 return s_ulFirstCallTick + (ULONG) (llCurrentTimeMS-s_ullFirstCallTickMS); 177}View Code [ping. cpp]
 1 #include <windows.h> 2 #include <stdio.h> 3 #include "ping.h" 4  5 int main(void)  6 { 7     CPing objPing;   8      9     char *szDestIP = "123.125.114.144";10     PingReply reply;11 12     printf("Pinging %s with %d bytes of data:\n", szDestIP, DEF_PACKET_SIZE);13     while (TRUE)14     {15         objPing.Ping(szDestIP, &reply);16         printf("Reply from %s: bytes=%ld time=%ldms TTL=%ld\n", szDestIP, reply.m_dwBytes, reply.m_dwRoundTripTime, reply.m_dwTTL);17         Sleep(500);18     }19     20     return 0;21 }

 

Execution result

 

Appendix: how to calculate the checksum

The algorithm for calculating the ICMP checksum is as follows:

1. Set the checksum field to 0.

2. Regard the data to be verified as a number in the unit of 16 bits, and sum the binary anticode in turn.

3. Save the result to the checksum field.

 

The so-called binary anticode summation is:

1. Convert the source data into an inverse code

2. 0 + 0 = 0 0 + 1 = 1 1 + 1 = 0 to 1

3. If the highest bit is added to generate carry, the final result will be incremented by 1.

 

In the actual implementation process, the common code syntax is:

1. Set the checksum field to 0.

2. Regard the data to be verified as a 16-bit number, and sum the data in turn to coexist in a 32-bit integer.

3. Add the high 16 bits (carry) in the sum result to the low 16 bits. If there are carry bits, repeat Step 1. [In fact, this step can be executed at most Twice]

4. The 32-bit integer is reversed by bit and forcibly converted to a 16-bit integer (truncation ).

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.