время эхо-ответа ICMP-пинга становится все короче и короче - PullRequest
0 голосов
/ 07 ноября 2019

Я написал программу для проверки связи с другим сервером, она работала хорошо (проверка прошла успешно, одноранговый сервер мог получить проверку связи и выполнить проверку связи), но я путаюсь с тем, почему время отклика становится все короче, время откликабыли около 100 мс раньше, через несколько секунд время отклика стало 2 мс или 1 мс.

Журнал печатался следующим образом:

from 10.9.9.9 msg_seq=1 ttl=64 rtt = 100 ms 
from 10.9.9.9 msg_seq=2 ttl=64 rtt = 102 ms 
from 10.9.9.9 msg_seq=3 ttl=64 rtt = 101 ms 
from 10.9.9.9 msg_seq=4 ttl=64 rtt = 100 ms 
........//after a few sencondes
from 10.9.9.9 msg_seq=280 ttl=64 rtt = 1 ms 
from 10.9.9.9 msg_seq=281 ttl=64 rtt = 2 ms 
from 10.9.9.9 msg_seq=282 ttl=64 rtt = 0 ms 

Пожалуйста, введите следующий код:

#define PING_PKT_S 64
#define PORT_NO 0
#define PING_SLEEP_RATE 1000000
#define RECV_TIMEOUT 1

int pingloop=1;

struct ping_pkt {
    struct icmphdr hdr;
    char msg[PING_PKT_S-sizeof(struct icmphdr)];
};

unsigned short checksum(void *b, int len) {
    unsigned short *buf = b;
    unsigned int sum=0;
    unsigned short result;

    for ( sum = 0; len > 1; len -= 2 )
        sum += *buf++;
    if ( len == 1 )
        sum += *(unsigned char*)buf;
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}


void intHandler(int dummy) {
    pingloop=0;
}

long current_timestamp() {
    struct timeval te;
    gettimeofday(&te, NULL);
    long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
    return milliseconds;
}


void display(void *buf, int bytes){
    int i;
    for ( i = (sizeof(struct iphdr)+sizeof(struct icmphdr)); i < bytes; i++ ){
        printf("%c", ((unsigned char*)buf)[i]);
    }
}

// make a ping request
void send_ping(int ping_sockfd, char *ping_ip) {
    int ttl_val=64, msg_count=0, i, addr_len, msg_received_count=0;

    struct ping_pkt pckt;
    struct sockaddr_in r_addr;
    struct timespec time_start, time_end;
    // set socket options at ip to TTL and value to 64,
    if (setsockopt(ping_sockfd, SOL_IP, IP_TTL,  &ttl_val, sizeof(ttl_val)) != 0) {
        printf("Setting socket options to TTL failed!\n");
        return;
    }else{
        printf("\nSocket set to TTL..\n");
    }
    // send icmp packet in an infinite loop
    while(pingloop) {
        if(isActiveNow()){
            printf("--current is active!\n");
            sleep(5);
            continue;
        }
        //filling packet
        bzero(&pckt, sizeof(pckt));

        pckt.hdr.type = ICMP_ECHO;
        pckt.hdr.un.echo.id = getpid();

        for ( i = 0; i < 10; i++ ){
            pckt.msg[i] = 'w';
        }
        pckt.msg[i] = 0;
        pckt.hdr.un.echo.sequence = msg_count++;
        pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));

        long s1 = current_timestamp();
        struct hostent *hostentObj;
        hostentObj = gethostbyname(ping_ip);
        struct sockaddr_in ping_addr;
        ping_addr.sin_port = 0;
        ping_addr.sin_family = hostentObj->h_addrtype;
        ping_addr.sin_addr.s_addr = *(long*) hostentObj->h_addr;

        //Using synchronize
        if ( sendto(ping_sockfd, &pckt, sizeof(pckt), 0,  (struct sockaddr*) &ping_addr, sizeof(ping_addr)) <= 0) {
            printf("\nPacket Sending Failed!\n");
        }

        struct timeval tv_out;
        tv_out.tv_sec = 10;
        tv_out.tv_usec = 0;

        struct sockaddr_in peerAddr;
        unsigned char buf[1024];
        int len=sizeof(peerAddr);

        bzero(buf, sizeof(buf));
        int bytes_received = recvfrom(ping_sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&peerAddr, &len);
        if (bytes_received > 0) {
          printf("ICMP packet received from %s\n", inet_ntoa(peerAddr.sin_addr));
          struct icmphdr *icmp = (struct icmphdr *) (buf + sizeof(struct iphdr));
          switch (icmp->type) {
              case ICMP_ECHOREPLY:{
                  printf("Type: ICMP_ECHO--REPLY----------\n");
                  long s2 = current_timestamp();
                  printf("from %s msg_seq=%d ttl=%d rtt = %ld ms \n", ping_ip, msg_count,ttl_val, (s2-s1));
                  display(buf, bytes_received);
                  break;
              };
              case ICMP_DEST_UNREACH:{
                  printf("Type: ICMP_DEST_UNREACH---WRONG\n");
                  failedNum++;
                  break;
              }
              case ICMP_SOURCE_QUENCH:  printf("Type: ICMP_SOURCE_QUENCH\n"); break;
              case ICMP_REDIRECT:       printf("Type: ICMP_REDIRECT\n"); break;
              case ICMP_ECHO:{
                  printf("Type: ICMP_ECHO-----\n");
                  long s2 = current_timestamp();
                  printf("from %s msg_seq=%d ttl=%d rtt = %ld ms \n", ping_ip, msg_count,ttl_val, (s2-s1));
                  display(buf, bytes_received);
                  break;
              }
              default: printf("Type: <0x%02x>\n", icmp->type); break;
          }
        }
    }
}

// Driver Code
int main(int argc, char *argv[]){
    int sockfd;
    char myIp[64]="10.1.1.10";
    char *peerIp = "10.9.9.9";

    sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
    struct sockaddr_in r_addr;
    r_addr.sin_family = AF_INET;
    r_addr.sin_addr.s_addr = inet_addr(myIp);
    r_addr.sin_port = 0;

    bind(sockfd, (struct sockaddr *) &r_addr, sizeof(r_addr));

    signal(SIGINT, intHandler);//catching interrupt

    //send pings continuously
    send_ping(sockfd,  peerIp);

    return 0;
}
...