How to code Ping in Windows

Source: Internet
Author: User
Tags cdata

I. Data Structure

First, define the data structure of the IP data packet header Based on the IP data packet format (figure ).

Typedef struct tagiphdr // ip packet header <br/>{< br/> u_char vihl; // version (4) + header length (4) <br/> u_char TOS; // service type (8) <br/> short totlen; // total length (16) <br/> short ID; // ID (16) <br/> short flagoff; // flag (3) + slice offset (13) <br/> u_char TTL; // TTL (8) <br/> u_short checksum; // header checksum (16) <br/> in_addr iasrc; // source IP address (32) <br/> in_addr iadst; // target IP address (32) <br/>} iphdr, * piphdr;

Then, the data structure of ICMP is defined based on the ICMP return request and Response Message format.

Typedef struct tagicmphdr // ICMP send-back request and response with ICMP packets <br/>{< br/> u_char type; // type (8) <br/> u_char code; // code (8) <br/> u_short checksum; // checksum (16) <br/> u_short ID; // identifier (16) <br/> u_short seq; // No. (16) <br/> char data; // optional data <br/>} icmphdr, * picmphdr;

 

Then define the Data Length of the request delivery respectively

# Define req_datasize 32

Data Structure of request delivery

Typedef struct tagechorequest <br/>{< br/> icmphdr; <br/> DWORD dwtime; <br/> char CDATA [req_datasize]; <br/>} echorequest, * pechorequest;

Data Structure of ICMP return response

Typedef struct tagechoreply <br/>{< br/> iphdr; <br/> echorequest; <br/> char cfiller [256]; <br/>} ECHOREPLY, * pechoreply;

 

Ii. function implementation

(1) sendechorequest

The function is used to send a send-back request packet. Three static variables are defined first.

Static echorequest echoreq; // data structure of the send-back request
Static nid = 1; // identifier
Static nseq = 1; // serial number

Then fill in the delivery request information

Echoreq. icmphdr. type = icmp_echoreq; // type
Echoreq. icmphdr. Code = 0; // code
Echoreq. icmphdr. checksum = 0; // checksum
Echoreq. icmphdr. ID = NID ++; // identifier

Echoreq. icmphdr. seq = nseq ++; // serial number

Enter the data to be sent
For (I = 0; I <req_datasize; I ++)
{
Echoreq. CDATA [I] = ''+ I;
}

Save sending time
Echoreq. dwtime = gettickcount ();

Store data in the package and calculate the checksum
Echoreq. icmphdr. checksum = in_chsum (u_short *) & echoreq, sizeof (echorequest ));

Send a return request
Nret = sendto (S,
(Lpstr) & echoreq,
Sizeof (echorequest ),
0,
(Lpsockaddr) lpsttoaddr,
Sizeof (sockaddr_in ));

(2) recvechoreply

Function to receive response data

 

 
DWORD recvechoreply (socket S, lpsockaddr_in lpsafrom, u_char * pttl)
{
ECHOREPLY; // Response Data Structure
Int nret;
Int naddrlen = sizeof (sockaddr_in );
// Accept the response
Nret = recvfrom (S,
(Lpstr) & ECHOREPLY,
Sizeof (ECHOREPLY ),
0,
(Lpsockaddr) lpsafrom,
& Naddrlen );
// Check the returned value
If (nret = socket_error)
{
Reporterror ("recvfrom ()");
}
* Pttl = ECHOREPLY. iphdr. TTL; // obtain the TTL value.
Return (ECHOREPLY. echorequest. dwtime); // return the time used
}
(3) waitforechoreply

Function: waits for the child s to read data.
Int waitforechoreply (socket S)
{
Timeval timeout;
Fd_set readfds;
Readfds. fd_count = 1;
Readfds. fd_array [0] = s;
Timeout. TV _sec = 5;
Timeout. TV _usec = 0;
Return (select (1, & readfds, null, null, & timeout ));
}

 

(3) in_chsum

Function compute checksum

U_short in_chsum (u_short * ADDR, int Len)
{
Register int nleft = Len;
Register u_short * w = ADDR;
Register u_short answer;
Register int sum = 0;
While (nleft> 1)
{
Sum + = * w ++;
Nleft-= 2;
}

If (nleft = 1)
{
U_short u = 0;
* (U_char *) (& U) = * (u_char *) W;
Sum + = u;
}

Sum = (sum> 16) + (sum & 0 xFFFF );
Sum + = (sum> 16 );
Answer = ~ SUM;
Return (answer );
}

(4) Implementation of the Main Function

Step 1: Define the Winsock Data Structure wsadata and create the version 1.1

Step 2: Call wsastartup to initialize wsadata

Step 3: Call the Ping function

Step 4: Call wsacleanup to release Winsock

Void main (INT argc, char ** argv)
{
Wsadata;
Word wversionrequested = makeword (1, 1); // winsock1.1
Int nret;

// Command line parameter check
If (argc! = 2)
{
Fprintf (stderr, "/nusage: Ping Hostname/N ");
Return;
}

// Initialize Winsock
Nret = wsastartup (wversionrequested, & wsadata );
If (nret)
{
Fprintf (stderr, "/nerror initializing Winsock/N ");
Return;
}

If (wsadata. wversion! = Wversionrequested)
{
Fprintf (stderr, "/nwinsock version not supported/N ");
Return;
}
// Call the Ping function
Ping (argv [1]);
// Ping ("www.sina.com ");
// Release Winsock
Wsacleanup ();
}

(5) Ping

Function: implements the Ping function.

Define the data used by the function

Socket rawsocket; // original socket
Lphostent lphost; // host information
Sockaddr_in sadest; // target address
Sockaddr_in sasrc; // Source Address
DWORD dwtimesent; // sending time
DWORD dwelapsed; // Delay Time

Then create an original socket

Create an original set of interfaces with the ICMP protocol
Rawsocket = socket (af_inet, sock_raw, ipproto_icmp );

Obtain from the target address entered by the user

Lphost = gethostbyname (pstrhost );

Set the target set interface address
Sadest. sin_addr.s_addr = * (u_long far *) (lphost-> h_addr ));
Sadest. sin_family = af_inet;
Sadest. sin_port = 0;

Output the prompt message of the Ping program.
Printf ("/npinging % s [% s] With % d bytes of data:/N ",
Pstrhost,
Inet_ntoa (sadest. sin_addr ),
Req_datasize );

Send an ICMP return request
Sendechorequest (rawsocket, & sadest );
Use select () to wait for receiving the response data

Waitforechoreply (rawsocket );
Receive response
Dwtimesent = recvechoreply (rawsocket, & sasrc, & cttl );
Calculate the transmission time and output the prompt.
Dwelapsed = gettickcount ()-dwtimesent;

Promised Response Information
Printf ("/nreply from: % s: bytes = % d time = % ldms TTL = % d ",
Inet_ntoa (sasrc. sin_addr ),
Req_datasize,
Dwelapsed,
Cttl );
}
// Close the socket
Nret = closesocket (rawsocket );

Appendix: program source code

// Ping. h <br/> // defines the structure of the IP address and ICMP header in this header file <br/> # pragma pack (1) <br/> # define ICMP_ECHOREPLY 0 <br/> # define icmp_echoreq 8 <br/> typedef struct tagiphdr // ip packet header <br/>{< br/> u_char vihl; // version (4) + header length (4) <br/> u_char TOS; // service type (8) <br/> short totlen; // total length (16) <br/> short ID; // ID (16) <br/> short flagoff; // sign (3) + part offset (13) <br/> u_char TTL; // TTL (8) <br/> u_short checksum; // header checksum (16) <br/> in_addr iasrc; // source IP address (32) <br/> in_addr iadst; // target IP address (32) <br/>} iphdr, * piphdr; <br/> typedef struct tagicmphdr // ICMP return request and ICMP packet <br/>{< br/> u_char type; // type (8) <br/> u_char code; // code (8) <br/> u_short checksum; // checksum (16) <br/> u_short ID; // identifier (16) <br/> u_short seq; // serial number (16) <br/> char data; // optional data <br/>} icmphdr, * picmphdr; <br/> // The length of the data returned by the request <br/> # define req_datasize 32 <br/> // the data structure of the ICMP return request <br/> typestrudef CT tagechorequest <br />{< br/> icmphdr; <br/> DWORD dwtime; <br/> char CDATA [req_datasize]; <br/>} echorequest, * pechorequest; <br/> // ICMP return response <br/> typedef struct tagechoreply <br/> {<br/> iphdr; <br/> echorequest; <br/> char cfiller [256]; <br/>} ECHOREPLY, * pechoreply; <br/> # pragma pack ()

 

// Ping. CPP <br/> // implement the simple Ping function <br/> # include <stdio. h> <br/> # include <stdlib. h> <br/> # include <Winsock. h> <br/> # include "Ping. H "<br/> void Ping (lpcstr pstrhost); <br/> void reporterror (lpcstr pstrfrom); <br/> int waitforechoreply (socket S ); <br/> u_short in_chsum (u_short * ADDR, int Len); <br/> // ICMP return request and response function declaration <br/> int sendechorequest (socket, lpsockaddr_in ); <br/> DWORD recvechoreply (socket, lpsockad Dr_in, u_char *); <br/> // Main Program <br/> void main (INT argc, char ** argv) <br/>{< br/> wsadata; <br/> word wversionrequested = makeword (1, 1); // winsock1.1 <br/> int nret; </P> <p> // command line parameter check <br/> If (argc! = 2) <br/>{< br/> fprintf (stderr, "/nusage: Ping Hostname/N"); <br/> return; <br/>}< br/> // initialize Winsock <br/> nret = wsastartup (wversionrequested, & wsadata); <br/> If (nret) <br/>{< br/> fprintf (stderr, "/nerror initializing Winsock/N"); <br/> return; <br/>}< br/> If (wsadata. wversion! = Wversionrequested) <br/>{< br/> fprintf (stderr, "/nwinsock version not supported/N"); <br/> return; <br/>}< br/> // call the Ping function <br/> Ping (argv [1]); <br/> // Ping ("www.sina.com "); <br/> // release Winsock <br/> wsacleanup (); <br/>}< br/> void Ping (lpcstr pstrhost) <br/> {<br/> socket rawsocket; // original socket <br/> lphostent lphost; // host information <br/> sockaddr_in sadest; // target address <br/> sockaddr_in sasrc; // source address <br/> DWORD dwtimesent; // Sending time <br/> DWORD dwelapsed; // delay time <br/> u_char cttl; <br/> int nloop; <br/> int nret; <br/> // create an original set of interfaces <br/> rawsocket = socket (af_inet, sock_raw, ipproto_icmp); <br/> If (rawsocket = socket_error) <br/>{< br/> reporterror ("socket ()"); <br/> return; <br/>}< br/> lphost = gethostbyname (pstrhost ); <br/> If (lphost = NULL) <br/> {<br/> fprintf (stderr, "/nhost not found: % s/n", pstrhost ); <br/> return; <br />}< Br/> // set the target set of interface addresses <br/> sadest. sin_addr.s_addr = * (u_long far *) (lphost-> h_addr); <br/> sadest. sin_family = af_inet; <br/> sadest. sin_port = 0; <br/> // output the Ping program prompt information <br/> printf ("/npinging % s [% s] With % d bytes of data: /n ", <br/> pstrhost, <br/> inet_ntoa (sadest. sin_addr), <br/> req_datasize); <br/> // control the number of Ping executions <br/> for (nloop = 0; nloop <4; nloop ++) <br/>{< br/> // send an ICMP return request <br/> sendechoreques T (rawsocket, & sadest); <br/> // use select () to wait for data to be sent back <br/> nret = waitforechoreply (rawsocket ); <br/> If (nret = socket_error) <br/>{< br/> reporterror ("select ()"); <br/> break; <br/>}< br/> If (! Nret) <br/>{< br/> printf ("/ntimeout/N"); <br/> break; <br/>}< br/> // receives a response <br/> dwtimesent = recvechoreply (rawsocket, & sasrc, & cttl); <br/> // calculates the transmission time, and output the prompt message <br/> dwelapsed = gettickcount ()-dwtimesent; <br/> printf ("/nreply from: % s: bytes = % d time = % ldms TTL = % d ", <br/> inet_ntoa (sasrc. sin_addr), <br/> req_datasize, <br/> dwelapsed, <br/> cttl); <br/>}< br/> printf ("/N "); <br/> // close the socket <br/> nret = closesock Et (rawsocket); <br/> If (nret = socket_error) <br/>{< br/> reporterror ("closesocket ()"); <br/>}< br/> int sendechorequest (socket S, lpsockaddr_in lpsttoaddr) <br/>{< br/> static echorequest echoreq; // data structure of the send-back request <br/> static nid = 1; // identifier <br/> static nseq = 1; // No. <br/> int nret; <br/> int I; <br/> // enter the return request information <br/> echoreq. icmphdr. type = icmp_echoreq; // type <br/> echoreq. icmphdr. code = 0; // Code <br /> Echoreq. icmphdr. checksum = 0; // checksum <br/> echoreq. icmphdr. id = NID ++; // identifier <br/> echoreq. icmphdr. SEQ = nseq ++; // serial number <br/> // enter the data to be sent <br/> for (I = 0; I <req_datasize; I ++) <br/> {<br/> echoreq. CDATA [I] = ''+ I; <br/>}< br/> // Save the sending time <br/> echoreq. dwtime = gettickcount (); <br/> // store data in the package and calculate the checksum. <br/> echoreq. icmphdr. checksum = in_chsum (u_short *) & echoreq, sizeof (echorequest); <br/> // send a return request <br/> Nret = sendto (S, <br/> (lpstr) & echoreq, <br/> sizeof (echorequest), <br/> 0, <br/> (lpsockaddr) lpsttoaddr, <br/> sizeof (sockaddr_in); <br/> If (nret = socket_error) <br/>{< br/> reporterror ("sendto () "); <br/>}< br/> return nret; <br/>}< br/> DWORD recvechoreply (socket S, lpsockaddr_in lpsafrom, u_char * pttl) <br/> {<br/> ECHOREPLY; // the data structure of the send-back response <br/> int nret; <br/> int naddrlen = sizeof (sockaddr_in ); <Br/> // receives the delivery response <br/> nret = recvfrom (S, <br/> (lpstr) & ECHOREPLY, <br/> sizeof (ECHOREPLY ), <br/> 0, <br/> (lpsockaddr) lpsafrom, <br/> & naddrlen ); <br/> // check the returned value <br/> If (nret = socket_error) <br/> {<br/> reporterror ("recvfrom ()"); <br/>}< br/> * pttl = ECHOREPLY. iPhone dr. TTL; // obtain the TTL value <br/> return (ECHOREPLY. echorequest. dwtime); // returned time <br/>}< br/> void reporterror (lpcstr pstrfrom) <br/>{< br/> fprintf (stde RR, "/n % d error:/N", wsagetlasterror ()); <br/>}< br/> // wait for the child s to read data <br/> int waitforechoreply (socket S) <br/>{< br/> timeval timeout; <br/> fd_set readfds; <br/> readfds. fd_count = 1; <br/> readfds. fd_array [0] = s; <br/> timeout. TV _sec = 5; <br/> timeout. TV _usec = 0; <br/> return (select (1, & readfds, null, null, & timeout )); <br/>}< br/> u_short in_chsum (u_short * ADDR, int Len) <br/>{< br/> Register int Nleft = Len; <br/> Register u_short * w = ADDR; <br/> Register u_short answer; <br/> Register int sum = 0; <br/> while (nleft> 1) <br/>{< br/> sum + = * w ++; <br/> nleft-= 2; <br/>}< br/> If (nleft = 1) <br/>{< br/> u_short u = 0; <br/> * (u_char *) (& U) = * (u_char *) W; <br/> sum + = u; <br/>}< br/> sum = (sum> 16) + (sum & 0 xFFFF); <br/> sum + = (sum> 16); <br/> answer = ~ SUM; <br/> return (answer); <br/>}

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.