Чому пінг набагато швидше, ніж сокети UDP?


1

Я намагаюся порівняти швидкість UDP-сокетів у моїй локальній мережі.

Здійснюючи перевірку мій локальної IP-адреси, я отримую час в обидві сторони ~ 80 мкс.

Я написав мінімальний UDP-сервер і клієнт для тестування латентності наступним чином. Клієнт і сервер працюють на одному хості, використовуючи той самий мережевий інтерфейс. Клієнт відправляє timeval на сервер через сокети дейтаграм, і при отриманні, сервер негайно приймає різницю між поточним timeval і отриманим timeval. Роблячи це, я отримую ~ 110 мікросекунд для односторонньої поїздки, в цілому близько ~ 220 мкс RTT.

Чому пінг набагато швидше, ніж моя програма?

cc udpserver.c -o udpserver
cc udpclient.c -o udpclient
./udpserver 4321
./udpclient 127.0.0.1 4321

udpserver.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

    void error(char *msg)
    {
        perror(msg);
        exit(1);
    }
    int main(int argc, char *argv[])
    {
         int sockfd, newsockfd, portno;
         struct timeval tval_recv, tval_now;
         struct sockaddr_in serv_addr;
         int n;

     /* Check arguments */
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }

     /* Set up socket */
     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     if (sockfd < 0)
        error("ERROR opening socket");

     /* Setup socket address for server */
     memset((char *) &serv_addr, '\0', sizeof(serv_addr));
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(atoi(argv[1]));

     /* Bind socket to socket address */
     if(bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              error("ERROR on binding");

     while(1) {
       n = recvfrom(sockfd, &tval_recv, sizeof(tval_recv), 0, NULL, NULL);

       if(n < 0)
         error("ERROR in recvfrom");

       gettimeofday(&tval_now, NULL);

       printf("%ld.%06ld\n", tval_now.tv_sec - tval_recv.tv_sec,
           (long int)(tval_now.tv_usec - tval_recv.tv_usec));
     }

     return 0;
}

udpclient.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

void error(char *msg) {
    perror(msg);
    exit(0);
}

int main(int argc, char **argv) {
    in_addr_t s_addr;
    int sockfd, portno, n;
    struct sockaddr_in serveraddr;
    struct timeval tval;
//    struct timespec ts_current;

    /* Check arguments */
    if (argc != 3) {
       fprintf(stderr,"Usage: %s <hostname> <port>\n", argv[0]);
       exit(0);
    }

    /* Create the socket */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
        error("Error opening socket");

    /* Set the socket address */
    s_addr = inet_addr(argv[1]);
    portno = atoi(argv[2]);
    memset((char *) &serveraddr, '\0', sizeof(serveraddr));
    memcpy(&serveraddr.sin_addr.s_addr, &s_addr, sizeof(s_addr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));

    /* Send packets */
    while(1) {
      gettimeofday(&tval, NULL);
//      clock_gettime(CLOCK_MONOTONIC, &ts_current);
      n = sendto(sockfd, &tval, sizeof(tval), 0, (struct sockaddr *)&serveraddr,
        sizeof(serveraddr));
      if(n < 0)
        error("ERROR in sendto");
      sleep(1);
    }

    return 0;
}

Відповіді:


3

Угадайте:

ping є інструментом, що використовує icmp протоколу. icmp знаходиться на шарі 3, мережевому шарі моделі OSI.

udpclient.c є інструментом, що використовує udp протоколу. udp знаходиться на шарі 4, транспортному шарі моделі OSI.

З кожним шаром до вихідних даних додаються додаткові дані. Як основний приклад: a icmp пакет містить IP-адресу джерела і IP-адресу призначення. A udp дейтаграма містить все це плюс e. g. інформацію про порт UDP. Ця інформація про порт повинна інтерпретуватися більш високим рівнем в мережному стеку.

Таким чином, UDP-пакети повинні сканувати на один рівень більше в мережевому стеку. Можна собі уявити, що сходити на 4-й поверх замість 3-го поверху. Це займе більше часу, але набагато довше, ніж 30 мкс.

Я вважаю, що ці 30 мкс складаються

  • розмір даних icmp проти udp
  • NIC / час драйвера / процесора для інкапсуляції та декапсуляції
  • Процесорний час, який udpclient.c використання
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.