#include <stdio.h> #include <sys/time.h> #include <signal.h> #include <arpa/inet.h> # Include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h&
Gt #include <netinet/ip.h> #include <netdb.h> #include <setjmp.h> #include <errno.h> #inc Lude <netinet/ip_icmp.h> #include <string.h> #include <stdlib.h> #define PACKET_SIZE 4096
/* */#define MAX_WAIT_TIME 5 #define Max_no_packets 3 char sendpacket[packet_size];
Char Recvpacket[packet_size];
int sockfd,datalen=56;
int nsend=0,nreceived=0;
struct sockaddr_in dest_addr;
pid_t pid;
struct sockaddr_in from;
struct Timeval tvrecv;
void statistics (int signo);
unsigned short cal_chksum (unsigned short *addr,int len);
int pack (int pack_no);
void Send_packet (void);
void Recv_packet (void);
int unpack (char* buf,int len);
void Tv_sub (struct timeval *out,struct timeval* in);
void statistics (int signo) {printf (\ n-----------------PING statistics----------------\ n);
printf ("%d packet transmitted,%d received,%%%d lost \ n", nsend,nreceived, (nsend-nreceived)/nsend*100);
Close (SOCKFD);
Exit (1);
/* CHECKSUM algorithm/* unsigned short cal_chksum (unsigned short *addr,int len) {int nleft=len;
int sum=0;
unsigned short *w=addr;
unsigned short answer=0;
/* Add ICMP header binary data to 2 bytes/while (nleft>1) {sum+=*w++;
nleft-=2; /* If the ICMP header is an odd number of bytes, the last byte is left.
The last byte is considered to be a high byte of 2 byte data, the low byte of this 2-byte data is 0, and continues to accumulate */if (nleft==1) {* (unsigned char *) (&answer) =* (unsigned char *) W;
Sum+=answer;
} sum= (sum>>16) + (SUM&0XFFFF);
sum+= (SUM>>16);
Answer=~sum;
return answer;
/* Set ICMP header/INT pack (int pack_no) {int packsize;
struct ICMP *icmpp;
struct Timeval *tval;
icmpp= (struct ICMP *) Sendpacket;
icmpp->icmp_type=icmp_echo;
icmpp->icmp_code=0;
icmpp->icmp_cksum=0; icmpp->icmp_seq=pack_no;
icmpp->icmp_id=pid;
Packsize=8+datalen;
tval= (struct timeval *) icmpp->icmp_data;
Gettimeofday (Tval,null)///* Record send Time/icmpp->icmp_cksum=cal_chksum ((unsigned short*) icmpp,packsize);/* CHECKSUM algorithm * *
return packsize;
* * * Send 3 ICMP message/void Send_packet () {int packetsize;
while (nsend<max_no_packets) {nsend++; Packetsize=pack (nsend)/* Set ICMP message/if (sendto (sockfd,sendpacket,packetsize,0, struct sockaddr *) &dest_addr,
sizeof (DEST_ADDR)) <0) {perror ("SendTo error");
Continue
Sleep (1);//* Send an ICMP message/}/* Every second to receive all ICMP messages/void Recv_packet () {int n,fromlen;
extern int errno;
* More Highlights: http://www.bianceng.cnhttp://www.bianceng.cn/programming/cplus/*/signal (sigalrm,statistics);
Fromlen=sizeof (from);
while (nreceived<10) {alarm (max_wait_time); if (N=recvfrom (sockfd,recvpacket,sizeof (Recvpacket), 0, (struct sockaddr *) &from,&fromleN)) {<0) {if (errno==eintr) {continue;
} perror ("Recvfrom error\n");
Continue } gettimeofday (&tvrecv,null);
/* Record receiving time/if (unpack (recvpacket,n) ==-1) continue;
nreceived++;
}/* Strip ICMP header/int unpack (char *buf,int len) {int iphdrlen;
struct IP *ipp;
struct ICMP *icmpp;
struct Timeval *tvsend;
int RTT;
ipp= (struct IP *) buf; Iphdrlen= (IPP->IP_HL) *4;/* the IP header length, that is, the length of the IP header by 4*/icmpp= (struct icmp*) (buf+iphdrlen);/* over IP header, pointing to ICMP header/* len-= IPHDRLEN;/*ICMP Header and ICMP datagram total length/if (len<8)/* Less than ICMP header length is not reasonable/{printf ("ICMP packets\ ' s length is less than
8\n ");
return-1; /* * Ensure that the received is a user's ICMP response */if ((icmpp->icmp_type==icmp_echoreply) && (icmpp->icmp_id==pid)) {TV
send= (struct timeval *) icmpp->icmp_data; Tv_sub (&tvrecv,tvsend); /* Receive and send time difference * * * rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000;/* in milliseconds rtt*//* Display Related information * * printf ("%d byte from%s:icmp_seq=%u ttl=%d rtt=%d ms\n", Len
, Inet_ntoa (FROM.SIN_ADDR), Icmpp->icmp_seq,ipp->ip_ttl,rtt);
else return-1; } void Tv_sub (struct timeval *out,struct timeval *in) {if (out->tv_usec-=in->tv_usec) <0) {out->
Tv_sec-=1;
out->tv_usec+=1000000;
} out->tv_sec-=in->tv_sec;
int main (int argc,char **argv) {struct hostent *host;
struct Protoent *protocol;
int size=50*1024;
if (argc<2) {printf ("Usage:%s HOSTNAME/IP address \ n", argv[0]);
Exit (1);
} if ((Protocol=getprotobyname ("ICMP")) ==null) {perror ("getprotobyname\n");
Exit (1); /* * Generate the original socket using ICMP, this socket is only root to generate/if ((Sockfd=socket (Af_inet,sock_raw,protocol->p_proto)) <0) {per
ROR ("Socket error\n");
Exit (1);
/* Reclaim root permissions, set current user rights/Setuid (Getuid ()); /* Enlarge socket receive buffer to 50K, mainly in order to reduce the possibility of receiving buffer overflow, if unintentionallyPing a broadcast address or multicast address, will lead to a large number of response/setsockopt (sockfd,sol_socket,so_rcvbuf,&size,sizeof (size));
Bzero (&dest_addr,sizeof (DEST_ADDR));
Dest_addr.sin_family=af_inet;
if ((Host=gethostbyname (argv[1])) ==null) {perror ("gethostbyname error\n");
Exit (1);
} dest_addr.sin_addr=* ((struct in_addr *) host->h_addr);
Pid=getpid ();
printf ("PING%s (%s):%d bytes data in ICMP packets.\n", Argv[1],inet_ntoa (DEST_ADDR.SIN_ADDR), datalen);
Send_packet ()/* Send all ICMP messages/Recv_packet ()/* Receive all ICMP messages/statistics (SIGALRM);/* for statistics/return 0; }
This article from the "Live Well" blog, please be sure to keep this source http://wolfword.blog.51cto.com/4892126/1225685