|
各位大虾请帮忙,小弟在linux下写了个ping程序,编译能够成功,但是运行就是问题,有时能通,有时不能通,总是解决不了,源程序以及运行结果帖如下:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
//#include <syslib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <setjmp.h>
//#define ICMP_HEADSIZE 8
//#define IP_HEADSIZE 20
#define datalen 56
#define MAX(a,b) ((a)>(b))?(a)b)
#define MIN(a,b) ((a)>(b))?(b)a)
/*typedef struct tagIpHead
{
u_char ip_verlen;
u_char ip_tos;
u_char ip_len;
u_char ip_id;
u_char ip_flagoff;
u_char ip_ttl;
u_char ip_proto;
u_short ip_chksum;
u_long ip_src_addr;
u_long ip_dst_addr;
}IPHEAD;
typedef struct tagIcmpHead
{
u_char icmp_type;
u_char icmp_code;
u_short icmp_chksum;
u_short icmp_id;
u_short icmp_seq;
u_char icmp_data[1];
}ICMPHEAD;*/
/*=====================================================
======================================================*/
u_short ChkSum(u_short *pIcmpData,int iDataLen)
{
u_short iSum;
u_short iOldByte=0;
unsigned short *w=pIcmpData;
int len=iDataLen;
iSum=0;
while(len>1)
{
iSum +=*w++;
len-=2;
}
if(len==1)
{
*(u_char*)(&iOldByte)=*(u_char*)w;
iSum+=iOldByte;
}
iSum=(iSum>>16)+(iSum&0xffff);
iSum+=(iSum>>16);
iOldByte=~iSum;
printf("chsum is %d\n",iOldByte);
return(iOldByte);
}
/*=====================================================
=====================================================*/
long time_now()
{
struct timeval now;
long lPassed;
gettimeofday(&now,0);
lPassed=now.tv_sec*1000000 + now.tv_usec;//化为微妙计算
return lPassed;
}
int time=1;
char * host;
char * prog;
extern errno;
long lSendTime;
u_short seq;
//int iTimeOut;
int sock,sent=0,recvd;
float max,min,total;
u_long lHostIp;
char buf[200];//发送缓冲区
char buf1[200];//接收缓冲区
struct sockaddr_in it;
struct sockaddr_in from;
pid_t pid;
int fromlen=sizeof(from);
int ping();
void stat();
main(int argc,char ** argv)
{
struct hostent*h;
//char buf1[200];
char dst_host[32];
int i,namelen;
int flag;
struct ip* pIpHead;
struct icmp* pIcmpHead;
struct protoent *protocol;
int size1=50*1024;
pid=getpid();
if(argc<2)
{
printf("usage:%s[-timeout]host}IP\n",argv[0]);
exit(0);
}
prog=argv[0];
host=argc==2?argv[1]:argv[2];
//iTimeOut=argc==2?1:atoi(argv[1]);
if((protocol=getprotobyname("icmp"))==NULL)
{
perror("getprotobyname");
exit(1);
}
if((sock=socket(AF_INET,SOCK_RAW,protocol->p_proto))<0)
{
perror("socket");
exit(2);
}
setuid(getuid);
setsockopt(sock,SOL_SOCKET,SO_RCVBUF,&size1,sizeof(size1));
bzero(&it,sizeof(it));
it.sin_family=AF_INET;
if((lHostIp=inet_addr(host))!=INADDR_NONE)
{
it.sin_addr.s_addr=lHostIp;
strcpy(dst_host,host);
}
else if(h=gethostbyname(host))
{
bcopy(h->h_addr,&it.sin_addr,h->h_length);
sprintf(dst_host,"%s(%s)",host,inet_ntoa(it.sin_addr));
}
else
{
fprintf(stderr,"bad IP or host\n");
exit(3);
}
namelen=sizeof(it);
printf("\nDigger pinging %s,send %d bytes\n",dst_host,datalen);
seq=0;
sigset(SIGINT,&stat);
for(;;)
{
register int size;//寄存器变量占用单独的一个寄存器,这样频繁使用该寄存器相对于读取内存来说效率就提高了 , 该类型变量只有int和char变量
register u_char ttl;
float delta;
register iIpHeadLen;
int len1;
ping();
size=recvfrom(sock,buf1,sizeof(buf1),0,(struct sockaddr *)&from,&fromlen);
if(size==-1 && errno==EINTR)
{
continue;
}
delta=(float)((time_now()-lSendTime)/1000.0);
pIpHead=(struct ip*)buf1;
iIpHeadLen=(int)((pIpHead->ip_hl&0x0f)<<2);//ip_hl中存放的是IP头部的长度,以4字节为单位。所以需要右移2位。
len1=size-iIpHeadLen;
if(len1<8)
{
printf("ICMP packets length is less than 8\n");
return (-1);
}
ttl=pIpHead->ip_ttl;
pIcmpHead=(struct icmp*)(buf1+iIpHeadLen);//越过IP报头,直接访问ICMP报头
if(pIcmpHead->icmp_type!=ICMP_ECHOREPLY)
{
fprintf(stderr,"i will continue for ICMPHEAD->type\n");
continue;
}
if(pIcmpHead->icmp_id!=pid || pIcmpHead->icmp_seq!=seq)
{
fprintf(stderr,"i will continue for ICMPHEAD->id/seq\n");
continue;
}
sprintf(buf1,"icmp_seq=%u bytes=%d ttl=%d",pIcmpHead->icmp_seq,len1,ttl);
fprintf(stderr,"reply from %s:%s time=%f ms\n",host,buf1,delta);
max=MAX(delta,max);
min=min?MIN(delta,min):delta;
total+=delta;
++recvd;
++seq;
printf("and now seq is %d\n",seq);
}
}
/*======================================================================
======================================================================*/
ping()
{
//char buf[200];
int iPacketSize;
struct timeval *tval;
long data=20;
struct icmp*pIcmpHead1=(struct icmp*)buf;
pIcmpHead1->icmp_type=ICMP_ECHO;
pIcmpHead1->icmp_code=0;
pIcmpHead1->icmp_id=pid;
pIcmpHead1->icmp_seq=seq;
pIcmpHead1->icmp_cksum=0;
fprintf(stderr,"but icmp_seq is %d\n",seq);
*((long*)pIcmpHead1->icmp_data)=data;
//tval=(struct timeval *)pIcmpHead1->icmp_data;
//gettimeofday(tval,NULL);
iPacketSize=datalen+8;
pIcmpHead1->icmp_cksum=ChkSum((u_short*)pIcmpHead1,iPacketSize);
lSendTime=time_now();
if(sendto(sock,buf,iPacketSize,0,(struct sockaddr*)&it,sizeof(it))<0)
{
perror("send failed");
exit(6);
}
printf("this time is No.%d\n",time++);
sleep(1);
++sent;
}
/*================================================================
=================================================================*/
void stat()
{
if(sent)
{
printf("\n----%s ping statistics summerized by Digger----\n",host);
printf("%d packets sent,%d packets received,%.2f%%lost\n",sent,recvd,(float)(sent-recvd)/(float)sent*100);
}
if(recvd)
{
printf("round_trip min/avg/max:%f/%f/%f ms\n\n",min,total/recvd,max);
}
exit(0);
}
运行结果:
letueo@letueo:/usr/local/program$ sudo ./ping letueo
Digger pinging letueo(127.0.1.1),send 56 bytes
but icmp_seq is 0
chsum is 59363
this time is No.1
i will continue for ICMPHEAD->type
but icmp_seq is 0
chsum is 59363
this time is No.2
reply from letueo:icmp_seq=0 bytes=64 ttl=64 time=1000.153015 ms
and now seq is 1
but icmp_seq is 1
chsum is 59362
this time is No.3
i will continue for ICMPHEAD->type
but icmp_seq is 1
chsum is 59362
this time is No.4
i will continue for ICMPHEAD->id/seq
but icmp_seq is 1
chsum is 59362
this time is No.5
i will continue for ICMPHEAD->type
but icmp_seq is 1
chsum is 59362
this time is No.6
reply from letueo:icmp_seq=1 bytes=64 ttl=64 time=1000.166016 ms
and now seq is 2
but icmp_seq is 2
chsum is 59361
this time is No.7
----letueo ping statistics summerized by Digger----
6 packets sent,2 packets received,66.67%lost
round_trip min/avg/max:1000.153015/1000.159546/1000.166016 ms |
|