sendto () не генерирует ошибку, если пункт назначения не существует - PullRequest
0 голосов
/ 19 октября 2018

Я использую функцию sendto() в C. Я установил адрес назначения и порт назначения.При отправке кадров UDP я вижу кадры в Wireshark, и количество пакетов, показанных в Wireshark, точно такое, как я определил в моей программе.

Проблема в том, что даже если адрес назначения недоступен, кадры отправляютсяи я вижу это в Wireshark.

Разве функция sendto() не должна выдавать ошибку, если IP-адрес назначения не существует?

 if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
                    (const struct sockaddr*)&server, sizeof(server)) < 0)
        {
            fprintf(stderr, "Error in sendto()\n");
            //return EXIT_FAILURE;
        }

Dest.IP: 234.168.0.1 Порт назначения: 80 или 9 (протокол сброса)

    #define PORT (80)
    #define FRAMES (20000)
    #define UDP_FRAME (1442)
    #define SERVERADDRESS "234.168.0.1"
    #define BUFFER_SIZE (FRAMES * UDP_FRAME)
    char buffer[BUFFER_SIZE];

    int main(int argc, char **argv)
{
    struct timespec start, end, loop_start, loop_end;
    int sockfd, count_frame = 0, frames_total, i = UDP_FRAME, n=1;
    struct sockaddr_in server;

    printf("Build Data...\n");
    build(buffer, sizeof(buffer));

    printf("Configure socket...\n");
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        fprintf(stderr, "Error opening socket");
        return EXIT_FAILURE;
    }

    /*----------------------------------------------------*/
/*---       Initialize address protocol            ---*/
/*----------------------------------------------------*/

    bzero((char*)&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(SERVERADDRESS);
    server.sin_port = htons(PORT);

    /*---------------------------------------------------*/
/*---       S E N D I N G   D A T A        --*/
/*---------------------------------------------------*/

    printf("\nSend UDP data...\n\n");
    clock_gettime(CLOCK_MONOTONIC_RAW, &start);
    clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
    frames_total = 0;

    for (int i = 0; i < BUFFER_SIZE; i += UDP_FRAME) {
    //while(1) {    

        if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
                    (const struct sockaddr*)&server, sizeof(server)) < 0)
        {
            fprintf(stderr, "Error in sendto()\n");
            //return EXIT_FAILURE;
        }
    count_frame += 1;

    clock_gettime(CLOCK_MONOTONIC_RAW, &loop_end);
    if ((loop_end.tv_nsec - loop_start.tv_nsec) > 5000000) {
        printf("\nCount [%d] ... ", n);
        printf("Fames sent: %d\n", count_frame);
        frames_total += count_frame;
        n+=1;
        count_frame = 0;
        clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
    }

    }
    printf("Total successful counted frames: %d \n", frames_total);

    return EXIT_SUCCESS;
}

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

UDP - ненадежный протокол.Вызов sendto успешен, как только пакет покидает интерфейс.После этого, независимо от того, добирается ли он до места назначения или нет, зависит от сети.

Даже если сеть поддерживает сообщения ICMP о том, что хост или порт недоступны, в вашем конкретном случае это не имеет значения, посколькувы отправляете на адрес многоадресной рассылки.Если у вас есть хотя бы один интерфейс с поддержкой многоадресной рассылки, система выберет один для отправки пакета.Он может быть получен несколькими (или нет) хостами.Поэтому нет смысла говорить, что пункт назначения недоступен.

0 голосов
/ 19 октября 2018

sendto() выдаст вам ошибку, если хост не знает маршрут к хосту (что почти никогда не происходит, так как ваш хост будет иметь шлюз по умолчанию).В противном случае вы могли бы (или не могли бы) получить сообщение о недоступности получателя ICMP, если ваш пакет не достиг целевого приложения, но это ненадежно и не будет передано при вызове sendto().

ЧтоВы можете запросить сокет с помощью

struct sock_extended_err err;
socklen_t errlen = sizeof(err);
getsockopt(fd, SOL_IP, IP_RECVERR, &err, &errlen);

на предмет полученных ошибок, что даст вам подробную информацию о полученных ошибках на сокете (т. е. недоступен порт ICMP, недоступен узел ICMP и т. п.).Это может помочь, но, как я уже сказал, это нереально, поскольку сообщения ICMP часто строго ограничены по скорости, фильтруются в пути или вообще не отправляются, если ваш пакет заблокирован фильтром пакетов (брандмауэр).

...