ping简单实现

#include "strings.h"
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/wait.h"
#include "errno.h"
#include "sys/select.h"
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/signal.h>

void handle_alarm(int signo);
void send_ip(void);
void recv_ip(void);
unsigned short ip_checksum(unsigned short *pcheck,int len);
int ip_fd;
int p_id;
const packet_len=8+20;
struct sockaddr_in send_addr;
char sendbuff[1024];
int sequence=0;

void handle_alarm(int signo){
 send_ip();
 alarm(2);
}
in_cksum(addr, len)
 u_short *addr;
 int len;
{
 register int nleft = len;
 register u_short *w = addr;
 register int sum = 0;
 u_short answer = 0;

 /*
  * Our algorithm is simple, using a 32 bit accumulator (sum), we add
  * sequential 16 bit words to it, and at the end, fold back all the
  * carry bits from the top 16 bits into the lower 16 bits.
  */
 while (nleft > 1)  {
  sum += *w++;
  nleft -= 2;
 }

 /* mop up an odd byte, if necessary */
 if (nleft == 1) {
  *(u_char *)(&answer) = *(u_char *)w ;
  sum += answer;
 }

 /* add back carry outs from top 16 bits to low 16 bits */
 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
 sum += (sum >> 16);   /* add carry */
 answer = ~sum;    /* truncate to 16 bits */
 return(answer);
}
void send_ip(void) {

 int len;
 struct icmphdr *icmp_p;
 icmp_p=(struct icmphdr *)sendbuff;
 icmp_p->type=ICMP_ECHO;
 icmp_p->code=0;
 (icmp_p->un).echo.id=p_id;
 (icmp_p->un).echo.sequence=sequence;
 gettimeofday((struct timeval *)(icmp_p+1),NULL);
 len=packet_len+sizeof(struct timeval);
 icmp_p->checksum=0;
 //icmp_p->checksum=ip_checksum(icmp_p,len);
 len=sendto(ip_fd,sendbuff,len,0,(struct sockaddr *)&send_addr,sizeof(send_addr));
 if(len<0)
  fprintf(stderr,"sendto error./n");
 sequence++;
 printf("sendto %s./n",inet_ntoa(send_addr.sin_addr));
}

void recv_ip(){
 char recv_buff[1024];
 struct ip *ip_p;
 struct icmphdr *icmp_p;
 int n;
 int len,iphead_len,icmp_len;
 struct timeval now,*time_now,*time_send;
 float delay;
 while(1){
 
  n=recvfrom(ip_fd,recv_buff,sizeof(recv_buff),0,NULL,NULL);
  if(n<0){
   if(errno==EINTR)
    continue;
   else {
    printf("recv error!");
    continue;
   }
  }
  ip_p=(struct ip *)recv_buff;
  iphead_len=ip_p->ip_hl<<2;
  icmp_len=n-iphead_len;
  if(icmp_len<8){
   fprintf(stderr,"error icmp_len=%d./n",icmp_len);
   return;
  }
  if(icmp_p->type==ICMP_ECHOREPLY){
   if((icmp_p->un).echo.id!=p_id)
    return;
   gettimeofday(&now,NULL);
   time_now=&now;
   time_send=(struct timeval *)(icmp_p +1);
   if((time_now->tv_usec-=time_send->tv_usec) < 0){
    time_now->tv_sec--;
    time_now->tv_usec+=1000000;
   }
   time_now->tv_sec-=time_send->tv_sec;
   delay=time_now->tv_sec*1000+time_now->tv_usec/1000;
    printf("%d bytes from %s:sequence:%d,ttl=%d,rtt=%dms/n",icmp_len,inet_ntoa(send_addr.sin_addr),(icmp_p->un).echo.sequence,ip_p->ip_ttl,delay);
  }
  
 }
}

int main(int argc, char **argv) {
 struct sigaction act;
 if(argc!=2) {
  fprintf(stderr,"usage:ping1 <ip adress>/n");
  return;
 }
 setuid((getuid()));
 act.sa_handler=handle_alarm;
 act.sa_flags=0;
 sigemptyset(&act.sa_mask);
 sigaction(SIGALRM,&act,NULL);
 p_id=getpid();
 inet_aton(argv[1],&send_addr.sin_addr);
 ip_fd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
 if(ip_fd < 0) {
  fprintf(stderr,"raw socket error./n");
  exit(1);
 }
 raise(SIGALRM);
 recv_ip();
}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值