/// Unit. CPP /////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////
//---------------------------------------------------------------------------
# Include <VCL. h>
# Pragma hdrstop
# Include "unit1.h"
//---------------------------------------------------------------------------
# Pragma package (smart_init)
# Pragma resource "*. DFM"
Tform1 * form1;
//---------------------------------------------------------------------------
_ Fastcall tform1: tform1 (tcomponent * owner)
: Tform (owner)
{
Edit1-> text = "127.0.0.1 ";
Edit2-> text = "64 ";
Edit3-> text = "1000 ";
Memo1-> lines-> clear ();
Seqindex = 0;
Recvpack = 0;
}
//---------------------------------------------------------------------------
Void _ fastcall tform1: button2click (tobject * sender)
{
Close ();
}
//---------------------------------------------------------------------------
Void _ fastcall tform1: button1click (tobject * sender)
{
Inisocket (); // initialization/aftercare
Ping (); // call the Ping function
}
//---------------------------------------------------------------------------
Void tform1: Ping () // The Ping function is completed.
{
Struct hostent * HP;
Char * strhost; // host address
Int ndatasize; // ICMP Packet Length
Int timeout;
Unsigned int ADDR = 0;
Unsigned int dw;
Word wversionrequested;
Wsadata;
Int err;
Wversionrequested = makeword (2, 2 );
Err = wsastartup (wversionrequested, & wsadata );
If (Err! = 0)
{
Memo1-> lines-> Add ("Winsock cannot be created. Check whether the related dynamic link library is missing ");
Return;
}
If (lobyte (wsadata. wversion )! = 2 |
Hibyte (wsadata. wversion )! = 2)
{
Memo1-> lines-> Add ("Winsock cannot be created. Check whether the related dynamic link library is missing ");
Wsacleanup ();
Return;
}
Inisocket ();
// Create a socket object for sending and receiving ICMP messages
If (invalid_socket = (sockraw = socket (af_inet, sock_raw, ipproto_icmp )))
{
Memo1-> lines-> Add ("unable to establish socket object ");
Return;
}
Timeout = edit3-> text. toint (); // you can specify the maximum waiting time.
If (socket_error = setsockopt (sockraw, sol_socket, so_rcvtimeo,
(Char *) & timeout, sizeof (timeout) |
(Socket_error = setsockopt (sockraw, sol_socket, so_sndtimeo,
(Char *) & timeout, sizeof (timeout ))))
{
Memo1-> lines-> Add ("socket error ");
Return;
}
Memset (& sadest, 0, sizeof (sadest); // initialize to 0
// Inet_addr () converts the vertex address to an integer address.
Strhost = edit1-> text. c_str ();
If (inaddr_none = (ADDR = inet_addr (strhost )))
{
// Gethostbyname () DNS domain name address
If (null = (HP = gethostbyname (strhost )))
{
Memo1-> lines-> Add ("Incorrect address ");
Return;
}
Else
{
Sadest. sin_family = hp-> h_addrtype;
Memcpy (& (sadest. sin_addr), HP-> h_addr, HP-> h_length );
}
}
Else
{
Sadest. sin_family = af_inet;
Sadest. sin_addr.s_addr = ADDR;
}
Packetsize = edit2-> text. toint ();
Ndatasize = packetsize + sizeof (icmpheader );
Picmpdata = new char [ndatasize];
Precvbuf = new char [ndatasize + maxipheader];
Memset (picmpdata, 0, ndatasize); // set 0
Fill_icmp_data (picmpdata, ndatasize); // fill in ICMP Packets
Seqindex = 0; // the serial number of this document
Recvpack = 0; // clear the number of received packets
Timer1-> enabled = true; // The timer starts to work.
}
Void tform1: inisocket () // complete initialization/aftercare
{
If (invalid_socket! = Sockraw)
{
Closesocket (sockraw );
Sockraw = invalid_socket;
}
If (null! = Picmpdata)
{
Delete picmpdata;
Picmpdata = NULL;
}
If (null! = Precvbuf)
{
Delete precvbuf;
Precvbuf = NULL;
}
}
Void tform1: fill_icmp_data (char * picmpdata, int ndatasize)
{
Icmpheader * picmphdr;
Char * pdatapart;
Picmphdr = (icmpheader *) picmpdata;
Picmphdr-> I _type = ICMP_Echo;
Picmphdr-> I _code = 0;
Picmphdr-> I _id = (ushort) getcurrentprocessid ();
Picmphdr-> I _seq = 0;
Pdatapart = picmpdata + sizeof (icmpheader );
Memset (pdatapart, 'E', ndatasize-sizeof (icmpheader ));
}
Void _ fastcall tform1: timer1timer (tobject * sender)
{
// Periodically sends ICMP Packets
Int nerror;
Int nwrite, nread;
Sockaddr_in from; // defines the remote socket link address.
Int nfromlen = sizeof (from );
Int ndatasize = packetsize + sizeof (icmpheader );
// If the maximum number of sent packets is exceeded, stop the ping operation.
If (seqindex> = maxnum)
{
Int lost; // message Loss Rate
Lost = (seqindex-recvpack) * 100/seqindex;
Memo1-> lines-> Add ("Lost =" + ansistring (lost) + "% ");
Timer1-> enabled = false;
Inisocket ();
Return;
}
// If the maximum number of sent packets is not exceeded, Ping
(Icmpheader *) picmpdata)-> I _cksum = 0;
(Icmpheader *) picmpdata)-> timestamp = gettickcount (); // Timestamp
(Icmpheader *) picmpdata)-> I _seq = 0 xFFFF & (seqindex ++); // number the message
(Icmpheader *) picmpdata)-> I _cksum = checksum (ushort *) picmpdata,
Ndatasize); // checksum
If (socket_error = (nwrite = sendto (sockraw, picmpdata, ndatasize, 0,
(Struct sockaddr *) & sadest, sizeof (sadest ))))
{
If (wsaetimedout = (nerror = wsagetlasterror ()))
{
Memo1-> lines-> Add ("timeout error ");
}
Else
{
Memo1-> lines-> Add ("message sending error ");
Timer1-> enabled = false; // stop sending packets
}
Return;
}
If (socket_error = (nread = recvfrom (sockraw, precvbuf,
Ndatasize + maxipheader, 0, (struct sockaddr *) & from, & nfromlen )))
{
If (wsaetimedout = (nerror = wsagetlasterror ()))
{
Memo1-> lines-> Add ("timeout error ");
} Else
{
Memo1-> lines-> Add ("receive data error ");
Timer1-> enabled = false; // stop sending packets
}
Return;
}
Decode_resp (precvbuf, nread, & from );
}
Ushort tform1: Checksum (ushort * databuffer, int size) // checksum Function
{
Unsigned long sum = 0;
While (1 <size)
{
Sum + = * databuffer ++;
Size-= sizeof (ushort );
}
If (size)
Sum + = * (uchar *) databuffer;
Sum = (sum> 16) + (sum & 0 xFFFF );
Sum + = (sum> 16 );
Return (ushort )(~ Sum );
}
//---------------------------------------------------------------------------
Bool tform1: decode_resp (char * buffer, int bytes, sockaddr_in * socketfrom)
{// The Program receives an IP message. In order to obtain the ICMP packet, the IP packet must be decomposed.
Ipheader * iphdr;
Icmpheader * icmphdr;
Unsigned short iphdrlen;
Iphdr = (ipheader *) buffer;
Ansistring strofping;
// Iphdrlen is measured in bytes, while the iphdr is measured in 32 bits.
Iphdrlen = iphdr-> h_len <2;
If (iphdrlen + icmp_min)> bytes)
{
Memo1-> lines-> Add ("the number of received bytes is too small ");
Return false;
}
Icmphdr = (icmpheader *) (buffer + iphdrlen );
If (ICMP_ECHOREPLY! = Icmphdr-> I _type)
{
Memo1-> lines-> Add ("type error ");
Return false;
}
If (icmphdr-> I _id! = (Ushort) getcurrentprocessid ())
{
Memo1-> lines-> Add ("not the datagram of this program ");
Return false;
}
++ Recvpack; // The message is correct. Add one to the accumulators.
Strofping = "reply from" + ansistring (inet_ntoa (socketfrom-> sin_addr ))
+ ":" + "Seq" + ansistring (icmphdr-> I _seq)
+ "Bytes =" + ansistring (bytes)
+ "Times =" + ansistring (gettickcount ()-icmphdr-> timestamp) + "Ms"
+ "TTL:" + ansistring (iphdr-> TTL );
Memo1-> lines-> Add (strofping );
Return true;
}
//---------------------------------------------------------------------------
///////////////// //////////////////////////////////////
//---------------------------------------------------------------------------
# Ifndef unit1h
# Define unit1h
//---------------------------------------------------------------------------
# Include <classes. HPP>
# Include <controls. HPP>
# Include <stdctrls. HPP>
# Include <forms. HPP>
# Include <extctrls. HPP>
# Include <winsock2.h>
# Define ICMP_Echo 8
# Define ICMP_ECHOREPLY 0
# Define icmp_min 8 // minimum ICMP header bytes
# Define maxipheader 60 // maximum number of IP datagram bytes
# Define maxnum 10 // defines the number of sent packets
// IP Header
Typedef struct tagipheader {
Unsigned char h_len: 4; // length of the header
Unsigned char 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 tagicmpheader
{
Byte I _type;
Byte I _code;
Ushort I _cksum;
Ushort I _id;
Ushort I _seq;
Ulong timestamp; // Timestamp
} Icmpheader;
//---------------------------------------------------------------------------
Class tform1: Public tform
{
_ Published: // ide-managed Components
Tmemo * memo1;
Tpanel * Panel1;
Tlabel * label1;
Tlabel * label2;
Tlabel * label3;
Tedit * edit1;
Tedit * edit2;
Tedit * edit3;
Tbutton * button1;
Tbutton * button2;
Ttimer * timer1;
Void _ fastcall button2click (tobject * sender );
Void _ fastcall button1click (tobject * sender );
Void _ fastcall timer1timer (tobject * sender );
PRIVATE:
Socket sockraw; // socket object
Char * picmpdata; // point to the ICMP Data Buffer
Char * precvbuf; // point to the receiving data buffer
Sockaddr_in sadest; // the destination address for storing Ping.
Int packetsize; // Data Length
Int seqindex; // the serial number of the message.
Int recvpack; // number of packets received
Void Ping ();
Void inisocket ();
Void fill_icmp_data (char * picmpdata, int ndatasize );
Ushort checksum (ushort * databuffer, int size); // checksum Function
// Data decoding function
Bool decode_resp (char * buffer, int bytes, sockaddr_in * socketfrom );
// User declarations
Public: // user declarations
_ Fastcall tform1 (tcomponent * owner );
};
//---------------------------------------------------------------------------
Extern package tform1 * form1;
//---------------------------------------------------------------------------
# Endif