linux c语言 mysql_ping()_linux下ping的C语言实现

#include#include#include#include#include#include#include#include#include#include#include#include#definePACKET_SIZE 4096#defineMAX_WAIT_TIME 5#defineMAX_NO_PACKETS 3charsendpacket[PACKET_SIZE];charrecvpacket[PACKET_SIZE];intsockfd,datalen=56;intnsend=0,nreceived=0;structsockaddr_in dest_addr;

pid_t pid;structsockaddr_in from;structtimeval tvrecv;voidstatistics(intsigno);

unsignedshortcal_chksum(unsignedshort*addr,intlen);intpack(intpack_no);voidsend_packet(void);voidrecv_packet(void);intunpack(char*buf,intlen);voidtv_sub(structtimeval*out,structtimeval*in);voidstatistics(intsigno)

{ printf("\n--------------------PING statistics-------------------\n");

printf("%d packets transmitted, %d received , %%%d lost\n",nsend,nreceived,

(nsend-nreceived)/nsend*100);

close(sockfd);

exit(1);

}/*校验和算法*/unsignedshortcal_chksum(unsignedshort*addr,intlen)

{intnleft=len;intsum=0;

unsignedshort*w=addr;

unsignedshortanswer=0;/*把ICMP报头二进制数据以2字节为单位累加起来*/while(nleft>1)

{ sum+=*w++;

nleft-=2;

}/*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/if( nleft==1)

{*(unsignedchar*)(&answer)=*(unsignedchar*)w;

sum+=answer;

}

sum=(sum>>16)+(sum&0xffff);

sum+=(sum>>16);

answer=~sum;returnanswer;

}/*设置ICMP报头*/intpack(intpack_no)

{inti,packsize;structicmp*icmp;structtimeval*tval;

icmp=(structicmp*)sendpacket;

icmp->icmp_type=ICMP_ECHO;

icmp->icmp_code=0;

icmp->icmp_cksum=0;

icmp->icmp_seq=pack_no;

icmp->icmp_id=pid;

packsize=8+datalen;

tval=(structtimeval*)icmp->icmp_data;

gettimeofday(tval,NULL);/*记录发送时间*/icmp->icmp_cksum=cal_chksum( (unsignedshort*)icmp,packsize);/*校验算法*/returnpacksize;

}/*发送三个ICMP报文*/voidsend_packet()

{intpacketsize;while( nsend

{ nsend++;

packetsize=pack(nsend);/*设置ICMP报头*/if( sendto(sockfd,sendpacket,packetsize,0,

(structsockaddr*)&dest_addr,sizeof(dest_addr) )<0)

{ perror("sendto error");continue;

}

sleep(1);/*每隔一秒发送一个ICMP报文*/}

}/*接收所有ICMP报文*/voidrecv_packet()

{intn,fromlen;externinterrno;

signal(SIGALRM,statistics);

fromlen=sizeof(from);while( nreceived

{ alarm(MAX_WAIT_TIME);if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,

(structsockaddr*)&from,&fromlen))<0)

{if(errno==EINTR)continue;

perror("recvfrom error");continue;

}

gettimeofday(&tvrecv,NULL);/*记录接收时间*/if(unpack(recvpacket,n)==-1)continue;

nreceived++;

}

}/*剥去ICMP报头*/intunpack(char*buf,intlen)

{inti,iphdrlen;structip*ip;structicmp*icmp;structtimeval*tvsend;doublertt;

ip=(structip*)buf;

iphdrlen=ip->ip_hl<<2;/*求ip报头长度,即ip报头的长度标志乘4*/icmp=(structicmp*)(buf+iphdrlen);/*越过ip报头,指向ICMP报头*/len-=iphdrlen;/*ICMP报头及ICMP数据报的总长度*/if( len<8)/*小于ICMP报头长度则不合理*/{ printf("ICMP packets\'s length is less than 8\n");return-1;

}/*确保所接收的是我所发的的ICMP的回应*/if( (icmp->icmp_type==ICMP_ECHOREPLY)&&(icmp->icmp_id==pid) )

{ tvsend=(structtimeval*)icmp->icmp_data;

tv_sub(&tvrecv,tvsend);/*接收和发送的时间差*/rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000;/*以毫秒为单位计算rtt*//*显示相关信息*/printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n",

len,

inet_ntoa(from.sin_addr),

icmp->icmp_seq,

ip->ip_ttl,

rtt);

}elsereturn-1;

}

main(intargc,char*argv[])

{structhostent*host;structprotoent*protocol;

unsignedlonginaddr=0l;intwaittime=MAX_WAIT_TIME;intsize=50*1024;if(argc<2)

{ printf("usage:%s hostname/IP address\n",argv[0]);

exit(1);

}if( (protocol=getprotobyname("icmp") )==NULL)

{ perror("getprotobyname");

exit(1);

}/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)

{ perror("socket error");

exit(1);

}/*回收root权限,设置当前用户权限*/setuid(getuid());/*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的

的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) );

bzero(&dest_addr,sizeof(dest_addr));

dest_addr.sin_family=AF_INET;/*判断是主机名还是ip地址*/if( inaddr=inet_addr(argv[1])==INADDR_NONE)

{if((host=gethostbyname(argv[1]) )==NULL)/*是主机名*/{ perror("gethostbyname error");

exit(1);

}

memcpy( (char*)&dest_addr.sin_addr,host->h_addr,host->h_length);

}else/*是ip地址*/memcpy( (char*)&dest_addr,(char*)&inaddr,host->h_length);/*获取main的进程id,用于设置ICMP的标志符*/pid=getpid();

printf("PING %s(%s): %d bytes data in ICMP packets.\n",argv[1],

inet_ntoa(dest_addr.sin_addr),datalen);

send_packet();/*发送所有ICMP报文*/recv_packet();/*接收所有ICMP报文*/statistics(SIGALRM);/*进行统计*/return0;

}/*两个timeval结构相减*/voidtv_sub(structtimeval*out,structtimeval*in)

{if( (out->tv_usec-=in->tv_usec)<0)

{--out->tv_sec;out->tv_usec+=1000000;

}out->tv_sec-=in->tv_sec;

}/*------------- The End -----------*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值