Source code full version of Microsoft Ping program

Source: Internet
Author: User
Tags socket blocking

Microsoft PingProgramSource codeFull Version

Author: Hou zhijiang

Writing a Ping program is the first step of network programming for many people !! Source of the Ping programCodeAfter my modifications and debugging, I can basically Replace the self-contained Ping program in windows. Each module has my detailed comments and modification logs, and I hope it will be helpful to everyone !!

/* The main source code of this program comes from the msdn website. I just made some improvements and comments! In addition, you must add the ws2_32.lib library file before building. Otherwise, an error "error lnk2001:" is displayed! */

/*************************************** ***************************************\

| Version 1.1 modification record: |

| <1> the socket blocking problem is solved, so that timeout requests can be correctly processed! |

| Bytes |

| Version 1.2 modification record: |

| <1> added the user-controlled ICMP packet sending function (the second parameter of the command). |

| <2> added the ping result statistics function. |

\*************************************** ***************************************/

# Pragma pack (4)

# Include

# Include

# Include

# Define ICMP_Echo 8

# Define ICMP_ECHOREPLY 0

# Define icmp_min 8 // minimum 8 byte ICMP packet (just header)

/* The IP header */

Typedef struct iphdr {

Unsigned int h_len: 4; // length of the header

Unsigned int version: 4; // version of IP

Unsigned char TOS; // type of service

Unsigned short total_len; // total length of the packet

Unsigned short ident; // Unique Identifier

Unsigned short frag_and_flags; // flags

Unsigned char TTL;

Unsigned char proto; // protocol (TCP, UDP etc)

Unsigned short checksum; // IP checksum

Unsigned int sourceip;

Unsigned int destip;

} Ipheader;

//

// ICMP Header

//

Typedef struct icmphdr {

Byte I _type;

Byte I _code;/* type sub Code */

Ushort I _cksum;

Ushort I _id;

Ushort I _seq;

/* This is not the STD header, But we reserve space for time */

Ulong timestamp;

} Icmpheader;

# Define status_failed 0 xFFFF

# Define def_packet_size 32

# Define def_packet_number 4/* Number of sent data packets */

# Define max_packet 1024

# Define xmalloc (s) heapalloc (getprocessheap (), heap_zero_memory, (s ))

# Define xfree (p) heapfree (getprocessheap (), 0, (p ))

Void fill_icmp_data (char *, INT );

Ushort checksum (ushort *, INT );

Int decode_resp (char *, Int, struct sockaddr_in *);

Void usage (char * progname ){

Fprintf (stderr, "Usage: \ n ");

Fprintf (stderr, "% s [number of packets] [data_size] \ n", progname );

Fprintf (stderr, "datasize can be up to 1kb \ n ");

Exitprocess (status_failed );

}

Int main (INT argc, char ** argv ){

Wsadata;

Socket sockraw;

Struct sockaddr_in DEST, from;

Struct hostent * HP;

Int bread, datasize, times;

Int fromlen = sizeof (from );

Int timeout = 1000;

Int statistic = 0;/* used for Statistics */

Char * dest_ip;

Char * icmp_data;

Char * recvbuf;

Unsigned int ADDR = 0;

Ushort seq_no = 0;

If (wsastartup (makeword (2, 1), & wsadata )! = 0 ){

Fprintf (stderr, "wsastartup failed: % d \ n", getlasterror ());

Exitprocess (status_failed );

}

If (argc <2 ){

Usage (argv [0]);

}

Sockraw = wsasocket (af_inet, sock_raw, ipproto_icmp, null, 0, wsa_flag_overlapped );

//

// Note: In order to use the sending and receiving timeout settings (that is, set so_rcvtimeo, so_sndtimeo ),

// The flag must be set to wsa_flag_overlapped!

//

If (sockraw = invalid_socket ){

Fprintf (stderr, "wsasocket () failed: % d \ n", wsagetlasterror ());

Exitprocess (status_failed );

}

Bread = setsockopt (sockraw, sol_socket, so_rcvtimeo, (char *) & timeout,

Sizeof (timeout ));

If (bread = socket_error ){

Fprintf (stderr, "failed to set Recv Timeout: % d \ n", wsagetlasterror ());

Exitprocess (status_failed );

}

Timeout = 1000;

Bread = setsockopt (sockraw, sol_socket, so_sndtimeo, (char *) & timeout,

Sizeof (timeout ));

If (bread = socket_error ){

Fprintf (stderr, "failed to set send Timeout: % d \ n", wsagetlasterror ());

Exitprocess (status_failed );

}

Memset (& DEST, 0, sizeof (DEST ));

HP = gethostbyname (argv [1]);

If (! HP ){

ADDR = inet_addr (argv [1]);

}

If ((! HP) & (ADDR = inaddr_none )){

Fprintf (stderr, "unable to resolve % s \ n", argv [1]);

Exitprocess (status_failed );

}

If (HP! = NULL)

Memcpy (& (DEST. sin_addr), HP-> h_addr, HP-> h_length );

Else

DeST. sin_addr.s_addr = ADDR;

If (HP)

DeST. sin_family = hp-> h_addrtype;

Else

DeST. sin_family = af_inet;

Dest_ip = inet_ntoa (DEST. sin_addr );

//

// The prototype of the atoi function is: int atoi (const char * string );

// The return value is 0 if the input cannot be converted to an integer!

//

If (argc> 2)

{

Times = atoi (argv [2]);

If (Times = 0)

Times = def_packet_number;

}

Else

Times = def_packet_number;

If (argc> 3)

{

Datasize = atoi (argv [3]);

If (datasize = 0)

Datasize = def_packet_size;

If (datasize> 1024)/* The data packet size given by the user is too large */

{

Fprintf (stderr, "Warning: data_size is too large! \ N ");

Datasize = def_packet_size;

}

}

Else

Datasize = def_packet_size;

Datasize + = sizeof (icmpheader );

Icmp_data = (char *) xmalloc (max_packet );

Recvbuf = (char *) xmalloc (max_packet );

If (! Icmp_data ){

Fprintf (stderr, "heapalloc failed % d \ n", getlasterror ());

Exitprocess (status_failed );

}


Memset (icmp_data, 0, max_packet );

Fill_icmp_data (icmp_data, datasize );

//

// Display prompt information

//

Fprintf (stdout, "\ npinging % s... \ n", dest_ip );


For (INT I = 0; I {

Int bwrote;

(Icmpheader *) icmp_data)-> I _cksum = 0;

(Icmpheader *) icmp_data)-> timestamp = gettickcount ();

(Icmpheader *) icmp_data)-> I _seq = seq_no ++;

(Icmpheader *) icmp_data)-> I _cksum = checksum (ushort *) icmp_data, datasize );

bwrote = sendto (sockraw, icmp_data, datasize, 0, (struct sockaddr *) & DEST, sizeof (DEST ));
If (bwrote = socket_error) {
If (wsagetlasterror () = wsaetimedout) {
printf ("request timed out. \ n ");
continue;

}< br>
fprintf (stderr," sendto failed: % d \ n ", wsagetlasterror ();
exitprocess (status_failed);

}< br>
If (bwrote fprintf (stdout, "W Rote % d bytes \ n ", bwrote);

}< br>
bread = recvfrom (sockraw, recvbuf, max_packet, 0, (struct sockaddr *) & from, & fromlen);
If (bread = socket_error) {
If (wsagetlasterror () = wsaetimedout) {
printf ("request timed out. \ n ");
continue;

}< br>
fprintf (stderr," recvfrom failed: % d \ n ", wsagetlasterror ();
exitprocess (status_failed);

}< br>
If (! Decode_resp (recvbuf, bread, & from)
statistic ++; /* Number of successfully received messages + + */
sleep (1000);

}

 

/*

Display the statistic result

*/

Fprintf (stdout, "\ nping statistics for % s \ n", dest_ip );

Fprintf (stdout, "packets: Sent = % d, received = % d, lost = % d (% 2.0f % loss) \ n", times,

Statistic, (times-statistic), (float) (times-statistic)/times * 100 );


Wsacleanup ();

Return 0;

}

/*

The response is an IP packet. We must decode the IP header to locate

The ICMP data

*/

Int decode_resp (char * Buf, int bytes, struct sockaddr_in * From ){

Ipheader * iphdr;

Icmpheader * icmphdr;

Unsigned short iphdrlen;

Iphdr = (ipheader *) BUF;

Iphdrlen = (iphdr-> h_len) * 4; // Number of 32-bit words * 4 = bytes

If (Bytes <iphdrlen + icmp_min ){

Printf ("too few bytes from % s \ n", inet_ntoa (from-> sin_addr ));

}

Icmphdr = (icmpheader *) (BUF + iphdrlen );

If (icmphdr-> I _type! = ICMP_ECHOREPLY ){

Fprintf (stderr, "non-echo type % d recvd \ n", icmphdr-> I _type );

Return 1;

}

If (icmphdr-> I _id! = (Ushort) getcurrentprocessid ()){

Fprintf (stderr, "someone else's packet! \ N ");

Return 1;

}

Printf ("% d bytes from % s:", bytes, inet_ntoa (from-> sin_addr ));

Printf ("icmp_seq = % d.", icmphdr-> I _seq );

Printf ("Time: % d MS", gettickcount ()-icmphdr-> timestamp );

Printf ("\ n ");

Return 0;

}


Ushort checksum (ushort * buffer, int size ){

Unsigned long cksum = 0;

While (size> 1 ){

Cksum + = * buffer ++;

Size-= sizeof (ushort );

}

If (size ){

Cksum + = * (uchar *) buffer;

}

Cksum = (cksum> 16) + (cksum & 0 xFFFF );

Cksum + = (cksum> 16 );

Return (ushort )(~ Cksum );

}

/*

Helper function to fill in various stuff in our ICMP request.

*/

Void fill_icmp_data (char * icmp_data, int datasize ){

Icmpheader * icmp_hdr;

Char * datapart;

Icmp_hdr = (icmpheader *) icmp_data;

Icmp_hdr-> I _type = ICMP_Echo;

Icmp_hdr-> I _code = 0;

Icmp_hdr-> I _id = (ushort) getcurrentprocessid ();

Icmp_hdr-> I _cksum = 0;

Icmp_hdr-> I _seq = 0;

Datapart = icmp_data + sizeof (icmpheader );

//

// Place some junk in the buffer.

//

Memset (datapart, 'E', datasize-sizeof (icmpheader ));

}

/********************* With the following attachment: screen displayed during Ping Command Execution ***************\

* C: \ Documents and Settings \ houzhijiang> Ping 236.56.54.12 *

**

* Pinging 236.56.54.12 with 32 bytes of data :*

**

* Request timed out .*

* Request timed out .*

* Request timed out .*

* Request timed out .*

**

* Ping statistics for 236.56.54.12 :*

* Packets: Sent = 4, received = 0, lost = 4 (100% loss ),*

**

\*************************************** ******************/

/*************************************** ******************\

* C: \ Documents ents and Settings \ houzhijiang> Ping 127.0.0.1 *

**

* Pinging 127.0.0.1 with 32 bytes of data :*

**

* Reply from 127.0.0.1: bytes = 32 time <1 ms TTL = 128 *

* Reply from 127.0.0.1: bytes = 32 time <1 ms TTL = 128 *

* Reply from 127.0.0.1: bytes = 32 time <1 ms TTL = 128 *

* Reply from 127.0.0.1: bytes = 32 time <1 ms TTL = 128 *

**

* Ping statistics for 127.0.0.1 :*

* Packets: Sent = 4, stored ED = 4, lost = 0 (0% loss ),*

* Approximate round trip times in Milli-seconds :*

* Minimum = 0 ms, maximum = 0 ms, average = 0 Ms *

**

\*************************************** *****************/

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.