鱼人下一代 任务:--Linux下的ping源码

来源:百度文库 编辑:九乡新闻网 时间:2024/03/29 23:50:28

已修改

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define IP_HEAD_LEN 20
#define ICMP_LEN 8

void send_icmp(int);
void recv_icmp(void);
unsigned short check_sum(unsigned short *addr, int len);

int sockfd;
char sendbuf[150];
char recvbuf[150];
struct sockaddr_in destaddr;
int my_icmp_id = 0;
int my_sequence = 400;
int send_num = 0;
int recv_num = 0;
float total_delay = 0.0;


/* Check Sum */
unsigned short check_sum(unsigned short *addr, int len)
{
    int nleft = len;
    unsigned short *w = addr;
    int sum = 0;
    unsigned short answer = 0;

    while (nleft > 1)
    {
        sum += *w++;
        nleft -= 2;
    }

    if (nleft == 1)
    {
        *(unsigned char *)(&answer)=*(unsigned char *)w;
        sum += answer;
    }

    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 stat()
{
    if(send_num)
    {
        printf("\n----ping    statistics    summerized    by    Digger----\n");
        printf("%d    packets    sent,    %d    packets    received,    %.2f%%    lost\n",
               send_num,recv_num,(float)(send_num-recv_num)/(float)send_num*100);
    }
    exit(0);
}

void send_icmp(int signo)
{
    int len;

    struct icmphdr *my_icmp = (struct icmphdr *)(sendbuf);
    my_icmp->type = ICMP_ECHO;
    my_icmp->code = 0;
    my_icmp->checksum = 0;
    (my_icmp->un).echo.id = my_icmp_id;
    (my_icmp->un).echo.sequence = my_sequence;
    gettimeofday((struct timeval *)(my_icmp+1), NULL);  //after plus 1, we get the address of icmp data because of the rule of pointer plus

    len = sizeof(struct timeval)+ICMP_LEN; 

    my_icmp->checksum = check_sum((unsigned short *)sendbuf, len);

    len = sendto(sockfd, sendbuf, len , 0, (struct sockaddr *)&destaddr, sizeof(struct sockaddr));

    if (len <= 0)
    {
        perror("fail to send!!\n");
        exit(1);
    }

    ++send_num;
    ++my_sequence;
    printf("sendto -----%s-----\n", inet_ntoa(destaddr.sin_addr));

    alarm(1);

}

 

void recv_icmp(void)
{
    struct timeval *time_now;
    struct timeval *time_send;
    struct timeval now;
    struct ip *my_ip;
    struct icmphdr *my_icmp;
    int n;
    int icmp_len;
    float delay;

    memset(recvbuf, '\0', 150); //应该这样做 初始化

    while(1)
    {
        n = recvfrom(sockfd, recvbuf, 150, 0, NULL, NULL);
        if (n < 0)
        {
            //perror("sth is wrong!\n");
            continue;
        }

        my_ip = (struct ip *)(recvbuf);
        my_icmp = (struct icmphdr *)(recvbuf+IP_HEAD_LEN); // 一定要注意,要加20(ip packet header);
        icmp_len = n;

        if (icmp_len < 8)
        {
            perror("echo is not right!\n");
            continue;
        }

        if (ICMP_ECHOREPLY == my_icmp->type)
        {
            if ((my_icmp->un).echo.id != my_icmp_id)
            {
                printf("the id is not right!\n");
                continue;
            }

            gettimeofday(&now, NULL);
            time_now = &now;
            time_send = (struct timeval *)(my_icmp+1);

            time_now->tv_sec -= time_send->tv_sec;
            time_now->tv_usec -= time_send->tv_usec;
            delay = time_now->tv_sec * 1000.0 + time_now->tv_usec/1000.0;
            ++recv_num;
            total_delay += delay;
            printf("%d bytes received and delay is %fms \n", icmp_len, delay);

        }
    }
}

int main(int argc, char **argv)
{
 if (2 != argc)
 {
  perror("using : ping IP\n");
  exit(1);
 }

 if (-1 == (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)))
 {
  perror("faild to socket\n");
  exit(1);
 }

 my_icmp_id = getpid() + 10;

 bzero(&destaddr, sizeof(struct sockaddr_in));
 destaddr.sin_family = AF_INET;
 inet_pton(AF_INET, argv[1], &destaddr.sin_addr.s_addr);
 bzero(sendbuf, 150);


    sigset(SIGINT,stat);
    signal(SIGALRM, send_icmp);
    alarm(1);

    recv_icmp();

}