Co to znaczy związać Gniazdo multicast (UDP)?

Używam multicast UDP między hostami, które mają wiele interfejsów sieciowych. Używam boost:: asio i jestem zdezorientowany 2 operacjami, które muszą wykonać: bind, następnie join-group.

Dlaczego musisz podać lokalny adres interfejsu podczas bind, gdy robisz to z każdą grupą multicastu, do której dołączysz?

Siostrzane pytanie dotyczy portu multicast: ponieważ podczas wysyłania wysyłasz na adres multicast & port, dlaczego podczas subskrypcji na Grupa multicast, można podać tylko adres, nie port-port jest określony w wywołaniu mylące do wiązania.

Uwaga:" join-group " jest opakowaniem setsockopt(IP_ADD_MEMBERSHIP), które, jak udokumentowano, może być wywołane wiele razy na tym samym gnieździe, aby zapisać się do różnych grup (w różnych sieciach?). Byłoby więc sensowne porzucenie wywołania bind i określenie portu za każdym razem, gdy subskrybuję grupę.

Z tego co widzę, zawsze wiąże się z "0.0.0.0" i określa adres interfejsu podczas dołączania do grupy działa bardzo dobrze. Zdezorientowany.

Author: Yves M., 2012-05-22

4 answers

Wiązanie gniazda UDP podczas odbierania multicastu oznacza określenie adresu i portu, z którego mają być odbierane dane(nie interfejsu lokalnego, jak to ma miejsce w przypadku akceptora TCP bind). Adres podany w tym przypadku ma rolę filtrowania , tzn. gniazdo będzie odbierać tylko datagramy wysyłane do tego adresu i portu multicastu, bez względu na to, jakie grupy zostaną następnie połączone przez gniazdo. To wyjaśnia, dlaczego podczas łączenia z INADDR_ANY (0.0.0.0) otrzymałem datagramy wysłane do mojej grupy multicast, natomiast przy wiązaniu z żadnym z lokalnych interfejsów nic nie otrzymałem, mimo że datagramy były wysyłane do sieci, do której ten interfejs korespondował.

Cytowanie z UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking API by W. R Stevens. 21.10. Wysyłanie i odbieranie

[...] Chcemy, aby Gniazdo odbierające wiązało grupę multicast i port, powiedzmy 239.255.1.2 port 8888. (Przypomnijmy, że możemy po prostu związać wildcard IP adres i port 8888, ale wiążący adres multicastu zapobiega odbieraniu przez gniazdo innych datagramów, które mogą / align= "left" / 88888) Następnie chcemy, aby Gniazdo odbierające dołącz do grupy multicast. Gniazdo wysyłające wyśle datagramy do ten sam adres i port multicastu, powiedzmy 239.255.1.2 port 8888.

 51
Author: haelix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-24 14:25:24

Operacja "bind" w zasadzie mówi: "użyj tego lokalnego portu UDP do wysyłania i odbierania danych. Innymi słowy, przydziela ten port UDP do wyłącznego użytku dla Twojej aplikacji. (To samo dotyczy gniazd TCP).

Gdy połączysz się z "0.0.0.0" (INADDR_ANY), w zasadzie każesz warstwie TCP/IP używać wszystkich dostępnych adapterów do nasłuchu i wybrać najlepszy adapter do wysyłania. Jest to standardowa praktyka dla większości kodów gniazd. Jedyny raz, kiedy nie podasz 0 dla adresu IP jest, gdy chcesz wysyłać/odbierać na określonej karcie sieciowej.

Podobnie jeśli podczas bind podasz wartość portu 0, SYSTEM OPERACYJNY przypisze losowo dostępny numer portu dla tego gniazda. Więc spodziewałbym się dla UDP multicast, wiązać INADDR_ANY na określonym numerze portu, gdzie ruch multicast ma być wysłany do.

Operacja "join multicast group" (IP_ADD_MEMBERSHIP) jest potrzebna, ponieważ w zasadzie mówi Twojej karcie sieciowej, aby nie nasłuchiwała tylko dla ramek ethernet, gdzie docelowy adres MAC jest własny, mówi również adapter ethernet (NIC), aby nasłuchiwał ruchu multicastowego IP, jak również dla odpowiedniego adresu ethernet multicast. Każdy adres multicast IP jest mapowany na adres multicast ethernet. Gdy używasz gniazda Wyślij do określonego adresu multicast IP, docelowy adres MAC w ramce ethernet jest ustawiany na odpowiedni adres MAC multicast dla adresu multicast. Gdy dołączasz do grupy multicast, konfigurujesz NIC do nasłuchiwania ruchu wysyłanego na ten sam adres MAC (oprócz własnego).

Bez wsparcia sprzętowego, multicast nie byłby bardziej wydajny niż zwykłe wiadomości IP. Operacja łączenia nakazuje również routerowi / bramce przesyłanie ruchu multicastowego z innych sieci. (Ktoś pamięta MBONE?)

Jeśli dołączysz do grupy multicast, cały ruch multicastowy dla wszystkich portów na tym adresie IP zostanie odebrany przez kartę sieciową. Tylko ruch przeznaczony dla Twojego binded Port nasłuchujący zostanie przekazany do aplikacji przez stos TCP / IP. W odniesieniu do tego, dlaczego porty są określone podczas subskrypcji multicast - to dlatego, że multicast IP jest tylko, że-tylko IP. "porty" są własnością górnych protokołów (UDP i TCP).

Możesz przeczytać więcej o tym, jak adresy IP multicast mapują adresy Ethernet multicast w różnych lokalizacjach. Artykuł w Wikipedii jest o tyle dobry, ile może być:

IANA posiada adres MAC OUI 01:00:5e, dlatego multicast pakiety są dostarczane za pomocą zakresu adresów MAC Ethernet 01:00: 5e:00:00:00 - 01:00:5e: 7f: ff: ff. Jest to 23 bity dostępnych przestrzeń adresowa. Pierwszy oktet (01) zawiera transmisję / multicast trochę. Niższe 23 bity 28-bitowego adresu IP multicast są mapowane do 23 bitów dostępnej przestrzeni adresowej Ethernet.

 41
Author: selbie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-22 04:16:34

Korekta dla Co to znaczy związać Gniazdo multicast (udp)? tak długo, jak jest to częściowo prawdziwe w poniższym cytacie:

Operacja "bind" w zasadzie mówi: "użyj tego lokalnego portu UDP do wysyłania i odbierania danych. Innymi słowy, przydziela ten port UDP do wyłącznego użytku dla Twojej aplikacji

Jest jeden szczególny przypadek. Wiele aplikacji Może współdzielić ten sam port do nasłuchu (zwykle ma praktyczną wartość dla datagramów multicast), jeśli zastosowana jest opcja 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);

Jeśli kilka procesów wykonało takie "powiązanie wielokrotnego użycia" , to każdy datagram UDP odebrany na tym współdzielonym porcie zostanie dostarczony do każdego z procesów (zapewniając naturalne połączenie z ruchem multicastów).

A) próba podłączenia dowolnego Bindu ("exclusive "lub" reuse") do wolnego portu zakończy się sukcesem

B) próba "ekskluzywnego wiązania" nie powiedzie się, jeśli port jest już "reuse-binded"

C) próba " ponownego użycia wiązania" nie powiedzie się, jeśli jakiś proces zachowa "ekskluzywne Wiązanie"

 8
Author: Yury Schkatula,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:08

Jest również bardzo ważne, aby odróżnić Gniazdo wysyłające multicast od gniazda odbierającego multicast.

Zgadzam się ze wszystkimi powyższymi odpowiedziami dotyczącymi odbierania gniazd multicast. OP zauważył, że powiązanie otrzymującego skt z interfejsem nie pomogło. Konieczne jest jednak powiązanie gniazda wysyłającego multicast do interfejsu.

Dla gniazda wysyłającego multicast na serwerze multi-homed, jest bardzo ważne, aby utworzyć osobne gniazdo dla każdego interfejsu, który chcesz Wyślij do. Dla każdego interfejsu należy utworzyć SKT wysyłania wiązanego.

  // 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) );
     }

Bez tej poprawki, wysyłanie multicastu będzie okresowo uzyskiwać SendTo () errno 'brak trasy do hosta'. Jeśli ktoś może rzucić światło na to, dlaczego odłączenie bramy DHCP powoduje, że gniazda wysyłania multicastów Mac OS X są zdezorientowane, chciałbym to usłyszeć.

 4
Author: Keith Knauber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 23:08:40