📄 ping.c
字号:
//==================================================================#include <stdio.h>#include <signal.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/socket.h>#include <unistd.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <netdb.h>#include <errno.h>#define ICMP_HEADSIZE 8 /* icmp packet header size */#define PACKET_SIZE 4096#define MAX_WAIT_TIME 1#define MAX_NO_PACKETS 4struct timeval tvsend,tvrecv;//struct sockaddr_in dest_addr,from;int sockfd;pid_t pid;//use the process id as ICMP's id//definition of fuctionsvoid timeout(int signo);void statistics(int signo);unsigned short cal_chksum(unsigned short *addr,int len);//int pack(int pkt_no,char *sendpacket);//int send_packet(int pkt_no,char *sendpacket);//int recv_packet(int pkt_no,char *recvpacket);int unpack(int cur_seq,char *buf,int len);//void tv_sub(struct timeval *out,struct timeval *in);void timeout(int signo){ printf("Request Timed Out\n"); exit(1);}/*checksum computing*/unsigned short cal_chksum(unsigned short *addr,int len){ int nleft=len; int sum=0; unsigned short *w=addr; unsigned short answer=0; while(nleft>1) { sum+=*w++; nleft-=2; } if( nleft==1) { *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return answer;}int pack(int pkt_no,char*sendpacket){ int i,packsize; struct icmp *icmp; struct timeval *tval; icmp=(struct icmp*)sendpacket; icmp->icmp_type=ICMP_ECHO; icmp->icmp_code=0; icmp->icmp_cksum=0; icmp->icmp_seq=pkt_no; icmp->icmp_id=pid; packsize=ICMP_HEADSIZE+sizeof(struct timeval); tval= (struct timeval *)icmp->icmp_data; gettimeofday(tval,NULL); icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); return packsize;}int send_packet(int pkt_no,char *sendpacket){ int packetsize; packetsize=pack(pkt_no,sendpacket); /*set the ICMP header*/ gettimeofday(&tvsend,NULL); if(sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0) { perror("sendto error"); return -1; } return 0;}int recv_packet(int pkt_no,char *recvpacket){ int n,fromlen; extern int errno; signal(SIGALRM,timeout); fromlen=sizeof(from); alarm(MAX_WAIT_TIME); while(1){ if( (n=recvfrom(sockfd,recvpacket,PACKET_SIZE,0,(struct sockaddr *)&from,&fromlen)) <0) { if(errno==EINTR)return -1; perror("recvfrom error"); return -2; } gettimeofday(&tvrecv,NULL); if(unpack(pkt_no,recvpacket,n)==-1)continue; return 0; }}int unpack(int cur_seq,char *buf,int len){ int iphdrlen; struct ip *ip; struct icmp *icmp; ip=(struct ip *)buf; iphdrlen=ip->ip_hl<<2; icmp=(struct icmp *)(buf+iphdrlen); len-=iphdrlen; if( len<8) return -1; if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) && (icmp->icmp_seq==cur_seq)) return 0; else return -1;}main(int argc,char *argv[]){ char sendpacket[PACKET_SIZE]; char recvpacket[PACKET_SIZE]; double rtt; char hostname[32]; struct hostent *host; struct protoent *protocol; int i,recv_status; if(argc!=2) { printf("usage:%s hostname/IPaddress\n",argv[0]); exit(1); } if( (protocol=getprotobyname("icmp") )==NULL) { perror("getprotobyname"); exit(1); } /* set destination host information */ strcpy(hostname,argv[1]); bzero(&dest_addr, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; if((host=gethostbyname(hostname))==NULL){ fprintf(stderr,"Cant get serverhost info!\n"); exit(1); } bcopy((char*)host->h_addr,(char*)&dest_addr.sin_addr,host->h_length); /* creat the raw socket for icmp */ if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { perror("socket"); exit(2); } /*get process id and used as icmp id*/ pid=getpid(); printf("PING %s(%s):\n",hostname,inet_ntoa(dest_addr.sin_addr)); for(i=0;i<MAX_NO_PACKETS;i++){ if(fork()==0) { if(send_packet(i,sendpacket)<0)continue; if(!recv_packet(i,recvpacket)){ tv_sub(&tvrecv,&tvsend); rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000; printf("reply from %s(%s): time=%.3f ms\n",hostname,inet_ntoa(dest_addr.sin_addr),rtt); exit(0); } } else wait(&recv_status); } return 0;}void tv_sub(struct timeval *out,struct timeval *in){ if( (out->tv_usec-=in->tv_usec)<0) { --out->tv_sec; out->tv_usec+=1000000; } out->tv_sec-=in->tv_sec;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -