Что означает привязка сокета многоадресной рассылки (UDP)?
Я использую многоадресный UDP между хостами, которые имеют несколько сетевых интерфейсов.
Я использую boost:: asio, и меня смущают 2 операции, которые приемники должны сделать: bind, затем join-group.
зачем вам нужно указывать локальный адрес интерфейса во время привязки, когда вы делаете это с каждой группой многоадресной рассылки, к которой вы присоединяетесь?
сестринский вопрос касается многоадресного порта: поскольку во время отправки вы отправляете на адрес и порт многоадресной рассылки, почему, во время подписка на многоадресную группу, вы указываете только адрес, а не Порт - Порт, указанный в запутанном вызове для привязки.
Примечание: "join-group" является оболочкой над setsockopt(IP_ADD_MEMBERSHIP), который, как указано в документе, может быть вызван несколько раз на одном сокете для подписки на разные группы (по разным сетям?). Поэтому имеет смысл отказаться от вызова bind и указывать порт каждый раз, когда я подписываюсь на группу.
от того, что я вижу, всегда привязка к "0.0.0.0" и указание адреса интерфейса при присоединении к группе, работает очень хорошо. Смущенный.
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 отправляет сокеты, чтобы запутаться, я хотел бы это услышать.
Comments