关于ping程序的问题
我写了一个简单的ping程序,代码如下:
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
void sigalrm_handler(int); //通过对alarm信号响应发送icmp数据包
void send_icmp(void);
void recv_icmp(void);
void tvsub(struct timeval *,struct timeval *); //calculate the transmission time
unsigned short in_cksum();//calculate the confirmation code
void pr_icmp(char *ptr,int len);
int sockfd;
int pid; //用于设置icmp的id
int datalen=56;//用于设置icmp数据包的打消
char hostname[128];
struct sockaddr_in dest;
char sendbuf[256];
int seq=0;//用于设置下一个icmp数据包的序列号
int main(int argc,char * argv[])
{
struct sigaction act;
struct hostent *he;
int n;
if(argc!=2)
{
fprintf(stderr,"usage:ping host\n");
exit(1);
}
act.sa_handler=sigalrm_handler;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGALRM,&act,NULL);//此函数用于检查或修改指定信号关联的处理动作
pid=getpid();
if(inet_aton(argv[1],&dest.sin_addr)==1)//若输入的是ip地址
{
strcpy(hostname,argv[1]);
}else{//若输入的是域名
he=gethostbyname(argv[1]);
if(he!=NULL)
{
strcpy(hostname,he->h_name);
dest.sin_addr=*(struct in_addr*)he->h_addr_list[0];
}else{
fprintf(stderr,"host name error:%s %s\n",argv[1],hstrerror(h_errno));
exit(1);
}
}
printf("PING %s(%s):\n",hostname,inet_ntoa(dest.sin_addr));
sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);//SOCK_RAW为原始套接字
if(sockfd<0)
{
fprintf(stderr,"socket error:%s\n",strerror(errno));
exit(1);
}
setuid(getuid());
sigalrm_handler(SIGALRM);
recv_icmp();
}
void recv_icmp(void)
{
char recvbuf[256];
int len;
int n;
for(;;)
{
n=recvfrom(sockfd,recvbuf,sizeof(recvbuf),0,NULL,NULL);
if(n<0)
{
if(errno==EINTR)
{
printf("recverro: EINTR\n");
continue;
}else{
printf("recvfrom error\n");
continue;
}
}
}
pr_icmp(recvbuf,n);
}
#define icmp_type type
#define icmp_code code
#define icmp_cksum checksum
#define icmp_id un.echo.id
#define icmp_seq un.echo.sequence
void pr_icmp(char *ptr,int len)
{
int hlen1,icmplen;
double rtt;
struct ip *ip;
struct icmphdr *icmp;
struct timeval *tvsend;
struct timeval tvrecv;
ip=(struct ip *)ptr;//是ip指向收到的数据包
hlen1=ip->ip_hl<<2;//ip_hl存储的是ip数据包首部的长度,是以4字节为单位的,将其右移两位得到ip数据包首部的长度
icmp=(struct icmphdr *)(ptr+hlen1);//与ip数据包首部相连的是icmp数据包
if((icmplen=len-hlen1)<8)//icmp应答数据包的首部长度为8字节
printf("icmplen(%d)<8\n",icmplen);
if(icmp->icmp_type==ICMP_ECHOREPLY)//判断该icmp数据包是否是应答数据包
{
printf("Received reply!\n");//测试
if(icmp->icmp_id!=pid) return;
if(icmplen<16)
printf("icmplen(%d)<16",icmplen);
gettimeofday(&tvrecv,NULL);
tvsend=(struct timeval *)(icmp+1);//与icmp数据包首部相连的是该icmp发送的时间,由于数据包头部为8字节,icmp指针加一就移动到发送时间项
tvsub(&tvrecv,tvsend);
rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000;
printf("%d bytes from %s(%s):seq=%u,ttl=%d,rtt=%.3f ms\n",icmplen,hostname,inet_ntoa(dest.sin_addr),icmp->icmp_seq,ip->ip_ttl,rtt);
}
}
void tvsub(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;
}
[解决办法]
blocking的recvfrom调用,被alarm信号打断了。
[解决办法]
[解决办法]
楼主的代码已经有这个的处理了阿,把printf拿掉,无视它即可
如果你说要不被打断的话,不幸得告诉你。。这是不可能的。
除非你去改linux内核