实现ping呼吁的代码
#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>
#include <netinet/ip.h>
#include <netdb.h>
#include <setjmp.h>
#include <errno.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <stdlib.h>
#define PACKET_SIZE 4096 /* */
#define MAX_WAIT_TIME 5
#define MAX_NO_PACKETS 3char 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);
}
/*校验和算法*/
unsigned short cal_chksum(unsigned short *addr,int len)
{
int nleft=len;
int sum=0;
unsigned short *w=addr;
unsigned short answer=0;
/*把ICMP报头二进制数据以2字节为单元累加起来*/
while(nleft>1)
{
sum+=*w++;
nleft-=2;
}
/*若ICMP报头为奇数个字节,会剩下最后一个字节。把最后一个字节视为2字节数据的高字节,这个2字节数据的低字节为0,继承累加*/
if(nleft==1)
{
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
return answer;
}
/*配置ICMP报头*/
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);/*记录发送时间*/
icmpp->icmp_cksum=cal_chksum((unsigned short*)icmpp,packsize);/*校验算法*/
return packsize;
}
/*发送3个ICMP报文*/
void send_packet()
{
int packetsize;
while(nsend<MAX_NO_PACKETS)
{
nsend++;
packetsize=pack(nsend);/*配置ICMP报文*/
if(sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr))<0)
{
perror("sendto error");
continue;
}
sleep(1);/*每隔一秒发送一个ICMP报文*/
}
}
/*吸收所有ICMP报文*/
void recv_packet()
{
int n,fromlen;
extern int errno;
/*