2014-09-18 4 views
0

Борясь последние два дня со следующими вопросами: выполняются ли шлейфные пакеты через точку доступа обратно отправителю, если отправитель подписан на группу многоадресной рассылки? Даже если это не так, можно ли заставить петлю через точку доступа?Почему отправитель не получает свой многоадресный UDP-пакет, если включен loopback?

Кроме того, почему не работает loopback со следующим кодом?

char * server_addr_name = "239.255.0.1"; // multicast group 
int port_number = 8888; 
int enable_loopback = 1; 
int udp_socket; 
struct message msg; // random message 
char buffer[BUFFER_SIZE]; 

/* create socket */ 
struct sockaddr_in server_addr, rcv_addr; 
socklen_t server_addr_size = sizeof(struct sockaddr_in); 
socklen_t rcv_addr_size = sizeof(struct sockaddr_in); 

/* initialize socket */ 
memset(& server_addr, 0, sizeof(struct sockaddr_in)); 
server_addr.sin_family = AF_INET; 
server_addr.sin_addr.s_addr = inet_addr(server_addr_name); 
server_addr.sin_port = htons(port_number); 
if ((udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 
    fprintf(stderr, "Error initializing UDP socket.\n"); 
    exit(EXIT_FAILURE); 
} 

struct ip_mreq mreq; 
mreq.imr_multiaddr.s_addr = inet_addr(server_addr_name); 
mreq.imr_interface.s_addr = htonl(INADDR_ANY); 
if (setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, & mreq, sizeof(mreq)) < 0) { 
    fprintf(stderr, "Error on setting multicast membership on socket.\n"); 
    exit(EXIT_FAILURE); 
} 
unsigned char do_enable = (unsigned char) enable_loopback; 
if (setsockopt(udp_socket, IPPROTO_IP, IP_MULTICAST_LOOP, 
       & do_enable, sizeof(do_enable)) < 0) { 
    fprintf(stderr, "Error on setting multicast loopback on socket.\n"); 
    exit(EXIT_FAILURE); 
} 

int read_size = 0; 
while (1) { 

    /* send the packet */ 
    if (sendto(udp_socket, &msg, sizeof(struct message), 0, 
      (struct sockaddr *) & server_addr, server_addr_size) == -1) { 
     fprintf(stderr, "Error on sending UDP packet.\n"); 
    } 
    else 
     printf("Sent my message.\n"); 

    /* get response from the server/multicast address */ 
    read_size = recvfrom(udp_socket, buffer, BUFFER_SIZE, 0, 
          (struct sockaddr *) & rcv_addr, & rcv_addr_size); 
    if (read_size < 1) 
     break; 
    else 
     printf("Got my packet!\n"); 
} 

Любая помощь оценивается.

+0

как вы тестируете? вы находитесь в тестовой среде, где отправитель и получатель находятся на одной машине? Если это так, я бы предложил попробовать с 127.0.0.1 в качестве IP и изменить файл ваших хостов, добавив строку: 127.0.0.1 имя хоста, где имя хоста - имя_компьютера. У меня иногда возникали такие проблемы. – Picarus

+0

@Picarus Это только делает все хуже. – EJP

+0

@ EJP, моя задача - сначала отладить проблему, чтобы определить, является ли она сетевой проблемой, а во-вторых, что иногда проблема заключается не в коде, а в конфигурации системы. Почему вы думаете, что это может быть хуже?Это может решить проблему или нет, но это может помочь принести свет. – Picarus

ответ

1

Аргументом для setsockopt() должен быть int, а не символ unsigned.

+0

Ну, это еще не исправило мою проблему. Никаких признаков петли. – user330293

+0

Это то, что именно? Какой код меняется? – EJP

+0

unsigned char do_enable -> int do_enable – user330293

1

Просто боролся с той же проблемой. Linux не будет отражать пакет в том же сокете, даже если он соответствует адресу: порт. Вы должны создать еще один сокет udp_socket_receiver так же, как ваш udp_socket и recvfrom будут работать. Похоже, что IP_MULTICAST_LOOP означает циклическое обращение многоадресных пакетов локально на всех прослушивателях, кроме сокета отправителя.

+1

Вы должны поделиться своими мыслями, указав в dos –

+0

. Это неправильно. Linux (я на 4.4.0) зеркально отображает многоадресные датаграммы для отправки сокета по умолчанию. Вам просто нужно убедиться, что сокет привязан к многоадресному sockaddr, подписанному на группу (используйте 'ip maddr' для проверки) и НЕ подключен. – wick

0

Выполняют ли шлейфные пакеты через точку доступа обратно отправителю, если отправитель подписан на группу многоадресной передачи?

Я не знаю точно, но на первый взгляд ответ жир Нет. Если шлюз отскакивает назад к месту, откуда он пришел, вы будете дублировать трафик, и это победит точку многоадресной рассылки.

Однако отправитель все равно получит сообщение, потому что любой в локальной сети, подписанный на группу, получит сообщение, и отправитель будет подписан.

Даже если это не так, возможно ли принудительное замыкание через точку доступа?

Я не знаю, но вам это, вероятно, не нужно. Смотри ниже.

Почему не работает loopback со следующим кодом?

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

Добавить следующий фрагмент между socket() и setsockopt(IP_ADD_MEMBERSHIP). Работа для меня:

struct sockaddr_in src; 
memset(&src, 0, sizeof(src)); 
src.sin_family = AF_INET; 
src.sin_port = htons(port_number); 
src.sin_addr.s_addr = INADDR_ANY; 
if (bind(udp_socket, (struct sockaddr*)&src, sizeof(src))) { 
    perror("bind() failed"); 
    close(udp_socket); 
    return EXIT_FAILURE; 
} 

Вы должны также, вероятно, будет close() ИНГ сокет всякий раз, когда вы сделали с ним.