Что означает привязка сокета многоадресной рассылки (UDP)?



Я использую многоадресный UDP между хостами, которые имеют несколько сетевых интерфейсов. Я использую boost:: asio, и меня смущают 2 операции, которые приемники должны сделать: bind, затем join-group.

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

сестринский вопрос касается многоадресного порта: поскольку во время отправки вы отправляете на адрес и порт многоадресной рассылки, почему, во время подписка на многоадресную группу, вы указываете только адрес, а не Порт - Порт, указанный в запутанном вызове для привязки.

Примечание: "join-group" является оболочкой над setsockopt(IP_ADD_MEMBERSHIP), который, как указано в документе, может быть вызван несколько раз на одном сокете для подписки на разные группы (по разным сетям?). Поэтому имеет смысл отказаться от вызова bind и указывать порт каждый раз, когда я подписываюсь на группу.

от того, что я вижу, всегда привязка к "0.0.0.0" и указание адреса интерфейса при присоединении к группе, работает очень хорошо. Смущенный.

200   4  

4 ответов:

привязать UDP сокет при получении многоадресной рассылки означает указать адрес и порт, с которого будут приниматься данные (не локальный интерфейс, как в случае с TCP acceptor bind). Адрес, указанный в этом случае имеет фильтрация роль, т. е. сокет будет получать только датаграммы, отправленные на этот адрес и порт групповой адресации, независимо от того, к каким группам впоследствии присоединяется сокет. Это объясняет, почему при привязке к INADDR_ANY (0.0.0.0) я получил датаграммы, отправленные в мою многоадресную рассылку группа, в то время как при привязке к любому из локальных интерфейсов я ничего не получал, хотя датаграммы отправлялись по сети, которой соответствовал этот интерфейс.

цитирование из UNIX® Network Programming Volume 1, третье издание: The Sockets Networking API by W. R Stevens. 21.10. Отправка и получение

[...] Мы хотим, чтобы принимающий сокет связывал группу многоадресной рассылки и порт, скажем 239.255.1.2 порт 8888. (Напомним, что мы могли бы просто привязать этот подстановочный IP-адрес и порт 8888, но привязка многоадресного адреса предотвращает получение сокетом любых других дейтаграмм, которые могут прибытие предназначено для порта 8888.) Затем мы хотим, чтобы приемный сокет присоединиться к группе многоадресной рассылки. Отправляющий сокет будет отправлять дейтаграммы этот же адрес многоадресной рассылки и порт, скажем, 239.255.1.2 порт 8888.

операция "привязка "в основном говорит:" используйте этот локальный UDP-порт для отправки и получения данных. Другими словами, он выделяет этот UDP-порт для эксклюзивного использования для вашего приложения. (То же самое справедливо и для сокетов TCP).

когда вы привязываетесь к" 0.0.0.0 " (INADDR_ANY), вы в основном говорите уровню TCP/IP использовать все доступные адаптеры для прослушивания и выбрать лучший адаптер для отправки. Это стандартная практика для большинства кодов сокетов. Единственный раз, когда вы не укажите 0 для IP-адреса, когда вы хотите отправить / получить на определенном сетевом адаптере.

аналогично, если вы укажете значение порта 0 во время привязки, ОС назначит случайно доступный номер порта для этого сокета. Поэтому я ожидал бы, что для многоадресной рассылки UDP вы привязываетесь к INADDR_ANY на определенном номере порта, куда, как ожидается, будет отправлен многоадресный трафик.

операция" join multicast group " (IP_ADD_MEMBERSHIP) необходима, потому что она в основном сообщает вашей сети адаптер для прослушивания не только для кадров ethernet, где MAC-адрес назначения является вашим собственным, он также сообщает адаптеру ethernet (NIC) для прослушивания IP-трафика многоадресной рассылки, а также для соответствующего адреса многоадресной передачи ethernet. Каждый многоадресный IP карты на широковещательный адрес сети Ethernet. При использовании сокета send to a specific multicast IP, MAC-адрес назначения на кадре ethernet устанавливается на соответствующий MAC-адрес многоадресной рассылки для IP многоадресной рассылки. При присоединении к группе многоадресной рассылки, вы настраиваете сетевой адаптер для прослушивания трафика, отправленного на тот же MAC-адрес (в дополнение к его собственному).

без аппаратной поддержки многоадресная рассылка не была бы более эффективной, чем обычные широковещательные IP-сообщения. Операция соединения также сообщает маршрутизатору / шлюзу о переадресации многоадресного трафика из других сетей. (Кто-нибудь помнит MBONE?)

Если вы присоединитесь к группе многоадресной рассылки, весь многоадресный трафик для всех портов на этом IP-адресе будет получен сетевой картой. Только трафик, предназначенный для вашего привязанного порта прослушивания, будет передан стеку TCP/IP в ваше приложение. Что касается того, почему порты указываются во время многоадресной подписки - это потому, что IP - адрес многоадресной рассылки-это только IP. "порты" - это свойство верхних протоколов (UDP и TCP).

вы можете прочитать больше о том, как многоадресные IP-адреса сопоставляются с многоадресными адресами ethernet на различных сайтах. Википедия примерно так же хорошо, как он получает:

IANA владеет OUI MAC-адрес 01: 00: 5e, поэтому многоадресная рассылка пакеты доставляются с помощью диапазона MAC-адресов Ethernet 01: 00: 5e:00:00:00 - 01:00:5e: 7f: ff: ff. Это 23 бита доступных адресное пространство. Первый октет (01) включает в себя широковещательную / многоадресную передачу немного. Нижние 23 бита 28-битного многоадресного IP-адреса сопоставляются в 23 бита доступного адресного пространства Ethernet.

коррекция что означает привязка сокета многоадресной рассылки (udp)? пока это частично верно по следующей цитате:

операция "привязка "в основном говорит:" используйте этот локальный UDP-порт для отправки и получения данных. Другими словами, он выделяет этот UDP-порт для эксклюзивного использования для вашего приложения

есть один особый случай. Несколько приложений можете общий доступ к одному порту для прослушивание (обычно это имеет практическое значение для многоадресных дейтаграмм) если применяется опция SO_REUSEADDR:

int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create UDP socket somehow
...
int set_option_on = 1;
// it is important to do "reuse address" before bind, not after
int res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, 
    sizeof(set_option_on));
res = bind(sock, src_addr, len);

если несколько процессов сделали такое "повторное связывание", то каждая датаграмма UDP, полученная на этом общем порту, будет доставлена каждому из процессов (обеспечивая естественное соединение с трафиком многоадресной рассылки).

а) попытка любого связывания ("эксклюзив" или "повторное использование") в Свободный порт будет удачным

b) попытка "эксклюзивной привязки" завершится неудачей, если порт уже "повторное использование привязанных"

c) попытка "повторного использования привязки" потерпит неудачу, если какой-то процесс сохраняет "эксклюзивную привязку"

также очень важно отличать отправляющий многоадресный сокет от принимающего многоадресного сокета.

Я согласен со всеми ответами выше относительно получения многоадресных сокетов. ОП отметил, что привязка получения skt к интерфейсу не помогла. Однако необходимо привязать сокет многоадресной отправки к интерфейсу.

для отправляющего многоадресного сокета на многосетевом сервере это очень создать отдельный сокет для каждого интерфейс, который вы хотите отправить. Связанный отправляющий skt должен быть создан для каждого интерфейса.

  // This is a fix for that bug that causes Servers to pop offline/online.
  // Servers will intermittently pop offline/online for 10 seconds or so.
  // The bug only happens if the machine had a DHCP gateway, and the gateway is no longer accessible.
  // After several minutes, the route to the DHCP gateway may timeout, at which
  // point the pingponging stops.
  // You need 3 machines, Client machine, server A, and server B
  // Client has both ethernets connected, and both ethernets receiving CITP pings (machine A pinging to en0, machine B pinging to en1)
  // Now turn off the ping from machine B (en1), but leave the network connected.
  // You will notice that the machine transmitting on the interface with
  // the DHCP gateway will fail sendto() with errno 'No route to host'
  if ( theErr == 0 )
  {
     // inspired by 'ping -b' option in man page:      
     //      -b boundif
     //             Bind the socket to interface boundif for sending.
     struct sockaddr_in bindInterfaceAddr;
     bzero(&bindInterfaceAddr, sizeof(bindInterfaceAddr));
     bindInterfaceAddr.sin_len = sizeof(bindInterfaceAddr);
     bindInterfaceAddr.sin_family = AF_INET;
     bindInterfaceAddr.sin_addr.s_addr = htonl(interfaceipaddr);
     bindInterfaceAddr.sin_port = 0; // Allow the kernel to choose a random port number by passing in 0 for the port.
     theErr = bind(mSendSocketID, (struct sockaddr *)&bindInterfaceAddr, sizeof(bindInterfaceAddr));
     struct sockaddr_in serverAddress;
     int namelen = sizeof(serverAddress);  
     if (getsockname(mSendSocketID, (struct sockaddr *)&serverAddress, (socklen_t *)&namelen) < 0) {
        DLogErr(@"ERROR Publishing service... getsockname err");
     }
     else
     {
        DLog( @"socket %d bind, %@ port %d", mSendSocketID, [NSString stringFromIPAddress:htonl(serverAddress.sin_addr.s_addr)], htons(serverAddress.sin_port) );
     }

без этого исправления многоадресная отправка будет периодически получать sendto () errno 'No route to host'. Если кто-нибудь может пролить свет на то, почему отключение шлюза DHCP приводит к тому, что Mac OS X multicast отправляет сокеты, чтобы запутаться, я хотел бы это услышать.

    Ничего не найдено.

Добавить ответ:
Отменить.