复制内容到剪贴板
代码:
# include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <errno.h>
#include <netinet/ip_icmp.h>
# define PACKSIZE 1024
char p_send[PACKSIZE];
char p_recv[PACKSIZE];
struct timeval *s_time,r_time;
pid_t pid;
struct sockaddr_in server_addr,source_addr;
int sockfd;
int nsend=1,nreceived=0;
void re_output(int signo);
unsigned short checksum(unsigned short *,int);
int p_pack(int );
void send_pack();
void recv_pack();
void unpack(char*,int );
void usedtime(struct timeval *,struct timeval *);
void p_socket();
void p_socket()
{
int n;
int size = 1024*50;
n=setuid(getuid()); //提升权限,好像没起作用,所以需要root用户
printf("%d\n",n);
struct protoent *proto;
if ((proto=getprotobyname("icmp"))==NULL)
{
printf("your enveriment wrong\n");
exit(1);
}
server_addr.sin_family = AF_INET;
bzero(&(server_addr.sin_zero), 8);
server_addr.sin_addr.s_addr=inet_addr("192.168.0.214");
//source_addr.sin_addr.s_addr=inet_addr("192.168.0.200");
if((sockfd=socket(AF_INET,SOCK_RAW,proto->p_proto))==-1)
{
fprintf(stderr,"socket error:%s\n",strerror(errno));
printf("creat a socket error\n");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) ); //set socket option 扩大缓冲区,防止益出
}
void re_output(int signo) //can shu que shao 打印输出,遇到中断就打印ctrl+c,还没调好
{
printf("%dpack sent,%dreceved, %d%%lost\n",nsend,nreceived,(nsend-nreceived)/nsend*100);
close(sockfd);
exit(1);
}
unsigned short checksum(unsigned short *addr,int len) //校验和
{
unsigned short *paddr=addr;
unsigned short fillbyte=0;
int sum, nleft=len;
while(nleft>1)
{
sum+=*paddr++;
nleft-=2;
}
if(nleft=1)
{
*(unsigned char *)(&fillbyte)=*(unsigned char *)paddr;
sum+=fillbyte;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
fillbyte=~sum;
return fillbyte;
}
int
p_pack(int seq)
{
struct icmp *icmp;
struct timeval *tval;
int datalen=56,pack_size;
icmp=(struct icmp*)p_send;
icmp->icmp_type=ICMP_ECHO;
icmp->icmp_code=0;
icmp->icmp_cksum=0;
icmp->icmp_seq=seq;
icmp->icmp_id=pid; //a check number,need to init
pack_size=8+datalen;
tval=(struct timeval *)icmp->icmp_data;
gettimeofday(tval,NULL);
//icmp->icmp_cksum=checksum(icmp,pack_size); // if else
icmp->icmp_cksum=checksum((unsigned short *)icmp,pack_size);
return pack_size;
}
void send_pack()
{
int packsize,back;
while(nsend<3) // send 2 packets
{
packsize=p_pack(nsend);
back=sendto(sockfd,p_send,packsize,0,(struct sockaddr*)&server_addr,sizeof(struct sockaddr_in));
if(back==-1)
{
fprintf(stderr,"send error:%s\n",strerror(errno));
close(sockfd);
return;
}
++nsend;
sleep(1);
}
}
void recv_pack()
{
int d_len,nback;
d_len=sizeof(source_addr);
signal(SIGALRM,re_output);
while(nreceived<=nsend) //小于等于发送个数
{
//select();
nback=recvfrom(sockfd,p_recv,PACKSIZE,0,(struct sockaddr*)&source_addr,&d_len);
printf("nback=%d\n",nback);
if(nback==-1) //inter of the computer;
{
printf("receive error\n");
continue;
}
gettimeofday(&r_time,NULL); //计下接收时间
unpack(p_recv,nback);
nreceived++;
}
}
void unpack(char *buff,int n) //拆包
{
int len=n;
struct ip *ip;
struct icmp *icmp;
int i,iphdrlen;
ip=(struct ip*)buff;
iphdrlen=ip->ip_hl<<2; //就是ip头的长度
icmp=(struct icmp*)(buff+iphdrlen);
len-=iphdrlen;
if(len<8)
{
printf("icmp pack length less than 8\n");
exit(1);
}
if((icmp->icmp_type==ICMP_ECHOREPLY)&&(icmp->icmp_id==pid))
s_time=(struct timeval*)icmp->icmp_data;
usedtime(&r_time,s_time);
printf("%d byte from %s: icmp_seq=%u ttl=%d \n",len,inet_ntoa(source_addr.sin_addr),icmp->icmp_seq,ip->ip_ttl);
}
void usedtime(struct timeval *t_recv,struct timeval *t_send) //计算发送和接收时间差
{
if(t_recv->tv_usec-=t_send->tv_usec<0)
{
--t_recv->tv_sec;
t_recv->tv_usec+=1000000;
}
t_recv->tv_sec-=t_send->tv_sec;
}
int
main(int argc, char **argv)
{
pid=getpid();
p_socket();
send_pack();
recv_pack();
re_output(SIGALRM);
return(1);
}